본문 바로가기

JAVA

231219 Java

접근 제어자 복습

package com.poseidon.access;

public class Test02 {
    public static void main(String[] args) {
        A a = new A();
        A.number = 10;
        System.out.println(A.number); // 클래스명.static 필드명, static 은 객체 없이도 사용 가능
        a.number = 100;
        System.out.println(a.number); // 100 출력
        System.out.println(A.number); // 100 출력, static 필드는 한개만 존재

        // B b = new B(); // 생성 불가
        B b = B.getInstance();
        B b2 = B.getInstance();
        B b3 = B.getInstance();
        B b4 = B.getInstance();
        b.setNum(1);
        b2.setNum(2);
        b3.setNum(3);
        b4.setNum(4);
        System.out.println(b.getNum()); // 4
        System.out.println(b2.getNum()); // 4
        System.out.println(b3.getNum()); // 4
        System.out.println(b4.getNum()); // 4
        // 객체를 여러 개 생성하여도 static 으로 인해 객체는 1 개만 존재
    }
}

class A {
    // final static int number1 = 0; // 미리 값 설정
    // final int number1; // 초기에 값 세팅
    static int number; // 기울어지는 것
    int num;

    // public A(int number1) { // static 이 아닌 final 객체는 생성자를 통해 초기 값 설정
    //     this.number1 = number1;
    // }
}
class B {
    static B b = null;
    private int num;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    private B() {
        System.out.println("생성자 입니다.");
    }
    public static B getInstance() {
        if (b == null) { // b 가 null 이면 새로운 객체 생성
            return b = new B();
        } else { // b 가 null 이 아니면 기존 객체 반환
            return b;
        }
    }
}

 

접근제한자, 오버라이딩 등

package com.poseidon.inheritance;

import dec19.Test03;

// 상속 + 접근 제어자 protected
class Animal extends Test03 {
    protected String name;
    int age;
    public void sleep() {
        testNumber = 10; // protected 는 상속으로 엮인 클래스 내부에서만 사용 가능
        // 객체 생성 시에는 사용 불가
    }
}
class Cat extends Animal {
    protected int catNumber;
    public void change() {
        testNumber = 10;
    }

    @Override // 어노테이션 = 표시 기능
    public void sleep() {
        // super.sleep();
        System.out.println("고양이가 침대에서 잠을 잡니다.");
    }
}
class Dog extends Animal {
    @Override
    public void sleep() {
        System.out.println(name + "이(가) 집에서 잠을 잡니다.");
    }
}

public class Inheritance extends Test03{ // 상속
    public static void main(String[] args) {
        Cat cat = new Cat();
        Dog dog = new Dog();
        cat.sleep();
        cat.name = "야옹";
        cat.catNumber = 1; // 호출 가능
        dog.age = 3;
        dog.sleep(); // 부모 클래스 필드 및 메소드 사용 가능
        // cat.testNumber = 10; // testNumber 필드에서는 default
        // cat.testMethod(); // Test03 클래스와 패키지가 달라 사용 어려움
        Inheritance inheritance = new Inheritance();
        System.out.println(inheritance.testNumber); // 상속받은 클래스에서만 사용 가능
    }
}

 

이해가 안가지만.. 다형성..

package polymorphism;
// 다형성 Polymorphism
/*
 * 다형성은 동적 바인딩이 지원되는 프로그램 언어에서 사용할 수 있음
 * 런타임 때 최종 타입이 결정
 * 하나의 객체가 여러가지 형태를 가질 수 있는 것
 *
 * 다형성을 활용하면 부모 클래스가 자식 클래스의 동작 방식을 알 수 없어도
 * 오버라이딩을 통해 자식 클래스에 접근할 수 있음
 *
 * 장점
 *  유지보수 : 여러 객체를 하나의 타입으로 관리할 수 있음
 *  재사용성 : 객체의 재사용이 쉬움
 *  느슨한 결합 : 클래스 간의 의존성을 줄여 확장성은 높아지고 결합도는 낮아짐
 *
 * 다형성의 조건
 * 상위 클래스와 하위 클래스는 상속 관계여야 함
 * 다형성이 보장되기 위해서 오버라이딩이 반드시 필요
 * 자식 클래스의 객체가 부모 클래스의 타입으로 형 변환 해야 함
 */
public class Polymorphism {
    public static void main(String[] args) {
        Ironman ironman = new Ironman();
        Hero h = new Ironman(); // 반드시 부모 클래스가 앞에 나와야 함
        ironman.makeSuit();
        // h.makeSuit(); // Hero 에는 해당 메소드가 없기 때문에 사용 불가, Hero 에 있는 것만 사용 가능
        h.attack(); // Ironman 클래스의 attack 메소드 실행, "레이저 공격" 출력
        Ironman mark2 = (Ironman) h;
        mark2.makeSuit(); // Ironman 클래스의 메소드를 사용할 수 있는 첫 번째 방법
        ((Ironman)h).makeSuit(); // 두 번째 방법
        Hulk hulk = new Hulk();
        hulk.attack(); // "주먹 공격" 출력
        // ((Ironman)hulk).makeSuit(); // 불가능
        // ((Ironman)((Hero)hulk)).makeSuit(); // 불가능
        System.out.println("-----------------");
        Hero[] avangers = new Hero[5];
        avangers[0] = new Ironman();
        avangers[1] = new Hulk();
        avangers[2] = new Superman();
        avangers[3] = new Xman();
        avangers[4] = new Ironman();
        for (Hero hero : avangers) {
            hero.attack();
        }
        Hero hero = new Hero(); // 이런 일을 방지하고자 추상화가 나옴
    }
}

class Hero {
    String name;
    void attack() {
        System.out.println("공격");
    }
}

class Ironman extends Hero {
    public void makeSuit() {
        System.out.println("자비스, 슈트 만들어");
    }
    @Override
    void attack () {
        System.out.println("레이저 공격");
    }
}

class Hulk extends Hero {
    @Override
    void attack() {
        System.out.println("주먹 공격");
    }
}

class Superman extends Hero {

}

class Xman extends Hero {

}

 

추상화

package abstractEx;
// 추상화
/*
 * 자바에는 추상화라는 개념이 있음
 * 추상 : 현실화 될 필요가 없는, 인스턴스화 할 필요가 없는 클래스
 *      -> 인스턴스화 할 필요가 없는 성질의 클래스
 * 추상화 된 클래스나 메소드는 상속 받은 클래스에서 완성 시켜야 함
 *
 * 자바에서는 객체지향을 통해 프로그램이 실행되는데
 * 추상이라는 개념을 클래스에 적용시키면 자신의 인스턴스를 발생할 수 없는 형태로 지정됨
 * 이렇게 인스턴스화 할 필요가 없지만 상속 개념에서 중요한 위치를 가지는 클래스를 보통 추상 클래스로 정의
 *
 * 선언 규칙
 *  1. 클래스에 정의된 메소드 중 추상 메소드가 하나라도 있다면 해당 클래스는 무조건 추상 클래스가 됨
 *     추상 클래스는 class 앞에 absract 라고 적음
 *  2. 추상 메소드는 메소드 바디가 없는 형태, 추상 메소드는 abstract 라는 키워드를
 *     리턴 타입 앞에 선언, 파라미터 괄호() 뒤에 세미콜론(;) 을 붙여 명령을 종료시킴
 *  3. 추상 클래스는 자신의 인스턴스를 발생시키지 못함
 *     하지만 생성자, 메소드, 필드는 모두 선언 및 정의 가능
 *     상속도 가능, 또한 Super type 으로 존재 가능하므로 다형성도 적용
 *  4. 추상 클래스가 되고 싶다면 class 앞에 abstract 를 붙이면 됨
 */
abstract class Hero { // 추상 클래스
    String name;
    int age;
    abstract void attack(); // 추상 메소드
    abstract void sleep();
    abstract void eat();
}
class Ironman extends Hero{
    @Override
    void attack() {
        System.out.println("레이저 공격");
    }
    @Override
    void sleep() { }
    @Override
    void eat() { }
}
class Hulk extends Hero {
    @Override
    void attack() {
        System.out.println("근육 공격");
    }
    @Override
    void sleep() { }
    @Override
    void eat() { }
}
class SpiderMan extends Hero{
    void attack () { // 미구현 된 메소드를 자식 클래스에서 구현
        System.out.println("거미줄 공격");
    }
    @Override
    void sleep() { }
    @Override
    void eat() { }
}
class Hawk_eye extends Hero {
    @Override
    void attack() {} // 바디 ({}) 만 열리면 구현한 것으로 인정됨
    @Override
    void sleep() { }
    @Override
    void eat() { }
}
public class AbstractEx {
    public static void main(String[] args) {
        // Hero hero = new Hero(); // 추상 클래스는 인스턴스 생성 불가
        Hero hero = new Ironman(); // 추상 클래스를 자식 클래스로 완성
        SpiderMan spiderMan = new SpiderMan();
        spiderMan.attack();
    }
}

 

추상화 두번째

package abstractEx;
/* 추상 클래스 : 인터페이스의 역할도 하면서 클래스 같은 돌연변이 클래스
 * 추상 클래스를 만들기 위해서 class 앞에 abstract 를 붙임
 * 내부 메소드에도 abstract 를 붙이고 바디를 제거
 * 인터페이스와 동일하게 메소드 바디 {} 가 없음
 *  -> 상속받는 자식 클래스에서 미구현된 메소드를 구현해야 함
 *
 * 추상 클래스 : 객체를 만들 수 없는 클래스 = 미완성된 기능이 있기 때문에 만들 수 없음
 * 추상 메소드 : 바디가 없는 메소드 (내용이 없음)
 *  미완성된, 구현이 없는, 바디가 없는 메소드 = 하위 클래스에서 구현 (오버라이드)
 *  하위 클래스에서 구현을 강제로 하게 함 = 프로그램 구조가 확실해 짐
 */
public class abstractEx2 {
}

 

클래스 이동 확인

package test;

public class Test01 {
    public static void main(String[] args) {
        A b = new B(); // B 클래스를 갖는 객체 생성
        b.paint(); // B 클래스의 paint 로 이동
        System.out.println("-");
        b.draw(); // BDCD - D 출력
    }
}
class A {
    public void paint() {
        System.out.println("A");
        draw();
    }
    public void draw() {
        System.out.println("B");
        draw(); // 객체 생성 시 참고한 클래스의 draw 메소드로 이동
    }
}
class B extends A {
    @Override
    public void paint () {
        super.draw(); // 부모 클래스의 draw 메소드 실행
        System.out.println("C");
        this.draw(); // 객체 생성 시 참고한 클래스의 draw 메소드로 이동
    }
    @Override
    public void draw() {
        System.out.println("D"); // D 출력하고 종료
    }
}

 

 

'JAVA' 카테고리의 다른 글

231221 Java  (2) 2023.12.21
231220 Java  (0) 2023.12.20
231218 Java  (0) 2023.12.18
231215 Java 객체지향  (0) 2023.12.15
231214 Java 객체지향  (2) 2023.12.14