package javajungsuk6_10;

public class Ch06_38a41 {
    
    public static void main(String[] args) {
        // 6-38 ~ 6-41 변수의 초기화, 멤버변수의 초기화

        // 지역변수는 수동으로 초기화를 해야한다.
        // 1. 명시적 초기화 (=): 대입연산자를 이용한 간단 초기화
        // 2. 인스턴스 초기화 - {} / static 초기화 - satic {}: 블럭을 이용한 복잡 초기화
        // 3. 생성자(iv)초기화

        Test test = new Test(); // 생성자에 있는 인스턴스의 x의 값을 출력하고 싶어서 객체를 생성했다.

        System.out.println("포인트 : 초기화의 순서 - cv >> iv >> 자동 >> 간단 >> 복잡으로 외우기");
        System.out.println("인스턴스 변수 : 유지력이 높기 때문에 자동 초기화를 한다.");
        System.out.println("지역변수 : 재사용이 빈번하면 성능이 떨어지기 때문에 자동 초기화를 하지 않는다.");
        System.out.println("참조형 변수가 가질 수 있는 값은 null과 객체주소다. null은 초기화를 한 것이 아니라 기본값이기 때문에 객체주소를 대입해준다.");
        System.out.println(Test.z); // 7
        System.out.println(test.x); // 10
    } // main의 끝
}

class Test {
    // 인스턴스 변수는 기본값으로 자동 초기화를 해주기 때문에 대입을 해도 에러가 나지 않는다.
    int x;
    int y = x;
    static int z = 5; // 클래스 변수의 명시적 초기화
    static {z = 7;} // 클래스 변수의 복잡 초기화
    {x = 1;} // 인스턴스 변수의 복잡 초기화

    // 생성자 초기화
    Test() {
        x = 10;
    }

    void method() {
        // int x; 지역변수는 메서드 호출 수행 시에만 존재하기 때문에 수명이 짧아 이것을 자동초기화를 하지는 않는다. 어떤 값인지 모르기 때문에 대입이 불가능하고 에러가 난다.

        // 올바른 예시
        int lvx = 10; // 값을 초기화 해주기
        int lvy =lvx; // 지역변수이지만 값을 초기화 해줬기때문에 대입이 가능해진다.
        System.out.println(lvy);
    }
} // class의 끝

class Reset {
    int a = 3; // 기본형 변수의 초기화
    Test lv = new Test(); // 참조형 변수의 초기화
}

package javajungsuk7;

public class Ch7_1a2 {
    
    public static void main(String[] args) {
        // 7-1~ 7-2 상속

        // 기존의 클래스로 새로운 클래스를 작성하는 것이다.(코드의 재사용)
        // 두 클래스를 부모와 자식으로 관계를 맺어주는 것이다.
        // 자손이 조상의 모든 멤버를 상속받는다.(생성자, 초기화 블럭 제외)

        Child c = new Child();

        System.out.println("자손의 변경은 조상에 영향을 미치지 않는다.");
        System.out.println(c.age); // Parent의 값을 상속받았기 때문에 Child에서도 age를 쓸 수 있다.

    } // main의 끝
}

class Parent {
    int age = 5; // 멤버 1개
} // class의 끝

class Child extends Parent{
    // Parent를 부모 클래스로 지정
    // Child자신의 멤버는 0개이지만, Child에 Parent의 멤버를 상속 받았기 때문에 Parent와 같이 멤버가 1개다.
    void play() { // Child에 play()라는 멤버를 추가해도 부모 클래스에는 영향이 없다.
        System.out.println("놀자~");

    }
}

package javajungsuk7;

public class Ch07_3a4 {
    
    public static void main(String[] args) {
        // 7-3 ~ 7-4 클래스 간의 관계, 상속과 포함

        // 포함 : 클래스의 멤버로 참조변수를 선언하는 것이다. / 상속보다는 포함을 많이 쓴다. 상속은 꼭 필요할 때만 쓴다.
        // 작은 단위의 클래스를 만들고, 그것들을 조합해서 클래스를 만든다.
        // 클래스 안에 멤버들을 여럿 쓰기 보다는 포함을 사용하여 한 클래스 안에 다른 클래스를 포함시키는 것이 깔끔하다.

        Circle c = new Circle(); // 이 객체 안에는 Point와 Circle 클래스가 들어있다.
        c.p.x = 10; // Circle안에 Point객체 안에 있는 x값은 10을 대입

        // 클래스 간의 관계 결정하기 쉬운 방법(어떤 것을 쓸지)
        System.out.println("상속관계 : ~이다.");
        System.out.println("포함관계 : ~은 ~을 가지고 있다.");

        System.out.println(c.p.x); // 10

    } // main의 끝
}

class Point {
    int x;
    int y;
} // class의 끝

class Circle { // Pount를 포함
    Point p = new Point();
    int r;

}

package javajungsuk7;

public class Ch07_5a6 {
    
    public static void main(String[] args) {
        // 7-5 ~ 7-6 단일상속, Object클래스

        // Java는 단일상속만 허용한다.
        // 부모가 없는 클래스는 자동적으로 extends object클래스를 상속받게 된다. / 컴파일러가 자동추가
        // 모든 클래스는 Object클래스에 정의된 11개의 메서드를 상속받는다. / toString(), equals(Object obj), hashCode()...

        Extends2 e2 = new Extends2();
        System.out.println("비중이 높은 클래스 하나를 상속관계로, 나머지는 포함관계로 한다.");
        System.out.println(e2); // 클래스 이름@객체주소값 / e2.toString()과 같은 것이다.
        System.out.println(e2.toString()); // Object클래스에 정의된 메서드이기 때문에 toString()을 호출할 수 있다.
        System.out.println(e2.e.a); // 3
        System.out.println(e2.b); // 5

    }
}

class Extends { // extends Object가 생략된 것이다.
    int a = 3;
}

class Extends2 { // 포함
    Extends e = new Extends();
    int b = 5;
}

package javajungsuk7;

public class Ch07_7a9 {
    
    public static void main(String[] args) {
        // 7-7 ~ 7-9 오버라이딩(Overriding)

        // 오버라이딩(Overriding) : 상속받은 조상의 메서드를 자신에 맞게 변경하는 것이다.
        // 오버라이드(Override) : 덮어쓰다.

        Teemo3D teemo3d = new Teemo3D();
        System.out.println(teemo3d.Teemo2()); // 오버라이딩을 한 값이 출력된다.

        // 오버라이딩의 조건
        System.out.println("선언부가 조상 클래스의 메서드와 일치해야 한다."); // 구현부(내용)만 변경이 가능하다.(선언부 X)
        System.out.println("접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다."); // public , private, protected, default
        System.out.println("예외는 조상 클래스의 메서드보다 많이 선언할 수 없다."); // 예외는 8장에서 배운다.
    } // main의 끝
}

class Teemo { // 티모 <^오^>
    int intersection = 500; // 사거리
    String affiliation = "Bandle City"; // 소속

    String Teemo2() {
        return "티모 대위, 명을 받들겠습니다!";
    }
} // class의 끝

class Teemo3D extends Teemo {
    String Ultimate = "Poisonous Mushroom"; // 궁극기

    String Teemo2() { // 부모의 Teemo2()를 오버라이딩
        return "티모 대위, 명을 받들겠습니다! <^오^> " + Ultimate +" : 내가 바로 티모다! <^오^>";
    }
}