package javajungsuk7_10;

public class Ch07_26 {
    
    public static void main(String[] args) {
        // 7-26 instanceof 연산자

        // instanceof 연산자 : 참조변수의 형변환 가능여부 확인에 사용한다. 가능하면 true를 반환한다.
        // 1. 반드시 확인을 하고 2. 형변환

        // instanceof를 쓸 때, 조심해야 할 것
        System.out.println("가능여부 : 실제 객체를 가리키는 게 그것이 맞는지 확인하는 것과 같다.");
        System.out.println("포인트 : 조상들은 다 true가 나오기때문에 조심해야 한다. 어떤 객체를 가리키는지 확인해야 한다.");
        System.out.println("최고 조상인 object와 참조변수의 가능여부를 확인하려하면 true");
        System.out.println("조상과 참조변수의 가능여부를 확인하려하면 true");
        System.out.println("자기 자신끼리의 가능여부를 확인하려하면 true");

        // 형변환
        System.out.println("형변환을 하는 이유? : 참조변수를 변경함으로써 사용가능한 멤버의 개수를 조절하기 위해서 형변환을 쓴다.");
        System.out.println("형변환을 한다고 해서 가리키는 객체가 달라지지는 않는다. 타입을 바꿔서 일치시키는 것이다."); // 객체와 주소값 모두 그대로다.
    }
}

package javajungsuk7_10;

public class Ch07_27a28 {
    
    public static void main(String[] args) {
        // 7-27 ~ 7-28 매개변수 다형성

        // 매개변수의 다형성 : 메서드 호출 시, 자신과 같은 타입 or 자손 타입의 인스턴스를 넘겨줄 수 있다.

        // 다형성의 장점2가지
        System.out.println("1. 다형적 매개변수 / 2. 하나의 배열로 여러종류 배열 다루기");

        
        // 다형성
        // 1. 자손 객체를 다루는 것
        // Wand w = new Star();
        // 2. 조상과 자식관계 / 참조변수 형변환
        // Wand w2 = (Wand)s;
        // 3. instanceof 연산자
        
        Star s = new Star();
        Marco m = new Marco();
        s.magic(m);
        System.out.println("Star의 나이는 " + s.age + "살이다.");
        System.out.println("Star의 자주 쓰는 마법은 " + s.rainbow);
    }
}

class Wand {
    int attackPower = 100;
    String rainbow = "Bling Bling Rainbow Punch!";
    String hornWhale = "Bling Bling Horn Whale Attack!";
} // class의 끝

class Marco extends Wand {}
class Star extends Wand {
    int age = 14;

    void magic(Wand w) { // 잘 모르겠다. 그냥 정리하면서 해봤다... 맞는지도 모르겠다.
        attackPower += w.attackPower;
    }
} // class의 끝

package javajungsuk7_10;

public class Ch07_29a30 {
    
    public static void main(String[] args) {
        // 7-29 ~ 7-30 여러 종류의 객체를 배열로 다루기

        // 조상타입의 배열에 자손 객체를 담을 수 있다.

        // Parent1 p1 = new Child1();
        // Parent1 p2 = new Child2();
        // Parent1 p3 = new Child3();

        // 위의 것을 배열로 더 간단하게
        // Parent1 p1[] = new Parent1[3];
        // p1[0] = new Child1();
        // p1[1] = new Child2();
        // p1[2] = new Child3();

        // 제일 간단하게 한줄로 작성
        Parent1 p1[] = {new Child1(), new Child2(), new Child3()};
        System.out.println(p1);
        

        // 참고
        System.out.println("Vector클래스(가변배열의 기능)라는 것이 있는데, object배열을 가지고 있어서 모든 종류의 객체들을 저장할 수 있다.");
        System.out.println("Vector클래스의 장점은 배열의 길이를 조절해준다. add()라는 메서드를 써서 배열에 추가만 해도 공간이 부족하면 늘려주고 많으면 줄여준다."); // 기본 배열은 한번 만들면 길이를 바꿀 수가 없다. 
    }
}

class Parent1 {

}

class Child1 extends Parent1 {}
class Child2 extends Parent1 {}
class Child3 extends Parent1 {}

package javajungsuk7_10;

public class Ch07_31a32 {
    
    public static void main(String[] args) {
        // 7-31 ~ 7-32 추상 클래스, 추상 메서드

        // 7-17 ~ 7-20 참고
        System.out.println("추상 클래스는 미완성된 설계도다. 따로 완성을 시켜주고 난 뒤 객체(제품)생성이 가능하다.");
        System.out.println("구상(구체) 클래스 : 추상 클래스를 상속받아서 완전한 클래스(설계도)를 만들어주는 클래스다."); // 상속을 통해 완성을 시킨 후 객체 생성 가능

        // 순서
        System.out.println("1. 상속을 통해 자손클래스 완성 / 2. 객체 생성 / 3. 호출");

        GamePlayer gp = new GamePlayer();
        gp.Teemo();
        gp.Ari();
        System.out.println(gp);
    }
}

// 추상클래스
abstract class Player {
    abstract void Teemo();
    abstract void Ari();
}

// 객체생성을 위해 만들어주는 클래스 : 추상클래스를 상속받아서 완성을 시켜줘야 한다.
class GamePlayer extends Player{
    // 추상클래스를 구현 : 구현부{}를 만들어주면 완성된 클래스가 되어 객체를 생성할 수 있게 된다.
    void Teemo() {
        String line = "Teemo : 티모 대위, 명을 받들겠습니다!";
        System.out.println(line);
    };

    void Ari() {
        String line = "Ari : 똑똑한 여우는 절대 잡히지 않거든.";
        System.out.println(line);
    };
}