package javajungsuk7_10;

public class Ch07_33a34 {
    
    public static void main(String[] args) {
        // 7-33 ~ 7-34 추상클래스의 작성(1) / 추상클래스의 작성(2)

        // 여러 클래스의 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존클래스의 공통부분을 뽑아서 추상클래스를 만든다.
        // 추상화 <-> 구체화

        System.out.println("추상화된 코드는 구체화된 코드보다 유연하다. / 변경에 유리");

        // 객체배열 : 참조변수 묶은 것
        Unit u[] = {new Marine(), new Tank(), new Dropship()};
        
        for(int i = 0; i < u.length; i++) {
            u[i].move(100, 200);
        }
        
        Object o[] = {new Marine(), new Tank(), new Dropship()};
        System.out.println(o);
        // 에러 : object는 최고 조상이기 때문에 객체배열을 생성할 수는 있지만 move()를 가지고 있지 않아서 에러가 난다.
        // for(int i = 0; i < u.length; i++) {
        //     o[i].move(100, 200);
        // }
    } // main의 끝
}

abstract class Unit {
    int x, y;
    abstract void move(int x, int y); // 지정된 위치로 이동
    void stop() {}; // 현재 위치에 정지
} // 추상클래스의 끝

// 보병
class Marine extends Unit {
    void move(int x, int y) {
        System.out.println("Marine[x = " + x + ", y = "+ y + " ]");
    };
    void stimPack() {};
}

// 탱크
class Tank extends Unit {
    void move(int x, int y) {
        System.out.println("Tank[x = " + x + ", y = "+ y + " ]");
    };
    void changeMode() {};
}

// 수송선
class Dropship extends Unit {
    void move(int x, int y) {
        System.out.println("Dropship[x = " + x + ", y = "+ y + " ]");
    };
    void load() {};
    void unload() {};
}

package javajungsuk7_10;

public class Ch07_35a37 {
    
    public static void main(String[] args) {
        // 7-35 ~ 7-37 인터페이스의 선언, 상속, 구현

        // 인터페이스(interface) : 추상메서드의 집합
        // 핵심은 구현된 것이 전혀없는 설계도, 껍데기다. (모든 멤버가 public)
        // 추상메서드를 완성하는 것이 구현이다.
        System.out.println("중요 포인트 : 추상클래스와 인터페이스의 차이점은 인터페이스는 iv를 가질 수 없고 추상메서드를 포함한다. 추상클래스는 생성자, iv 가능하다.");
        System.out.println("인터페이스의 조상은 인터페이스만 가능하다. object X");
        System.out.println("추상클래스와 다르게 다중상속이 가능하다. 추상메서드는 충돌해도 문제가 없다. 선언부가 일치하고 구현부가 없는 경우 가능하다.");
    }
}

interface Interface {
    public static final int test = 3; // 상수 : public static final 생략가능
    public abstract String test2(); // 추상메서드 : public abstract 생략가능
    void move(int x, int y);
    void attack(Unit u);
}

// 생략가능 확인
interface Interface2 {
    int test = 3;
    String test2();
}

// 인터페이스를 상속받으려면 implements(구현)를 써야한다. / 일부만 구현하는 경우 앞에 abstract를 붙여야 한다. / 추상클래스와 동일
abstract class Fightable implements Interface {
    public void move(int x, int y){
        System.out.println("x = " + x + ", y = " + y);
    };
    public void attack(Unit u){
        System.out.println("");
    };
}

package javajungsuk7_10;

public class Ch07_38 {
    
    public static void main(String[] args) {
        // 7-38 인터페이스와 다형성

        System.out.println("중요 포인트 : 매개변수가 인터페이스라는 것은 인터페이스를 구현한 클래스의 객체만 들어올 수 있다는 것이다.");
        System.out.println("인터페이스를 메서드의 리턴타입으로 지정할 수 있다."); // 인터페이스를 구현한 클래스의 객체를 반환하는 것이다.

        Fightable1 f = new Fighter1();
        f.move(100, 200);
        f.attack(new Fighter1()); // Fightable 인터페이스를 구현한 Fighter클래스의 객체
    }
}

interface Fightable1 {
    // 인터페이스의 모든 메서드는 public abstract 예외없이.
    void move(int x, int y);
    void attack(Fightable1 f);

}

// 7-33 ~ 7-34의 Unit을 가져옴
class Fighter1 extends Unit implements Fightable1 {
    // 오버라이딩 규칙 : 조상(public)보다 접근제어자 범위가 좁으면 안 된다. / public을 붙여주지 않으면 default라 범위가 좁아서 안 된다.
    public void move(int x, int y) {
        System.out.println("이동");
    }
    public void attack(Fightable1 f) {
        System.out.println("공격");
    }
    // 리턴타입
    Fightable1 method() {
        Fightable1 f = new Fighter1();
        return f;
    }
}