package javajungsuk7_10;

class Ch07_10a11 {
    
    public static void main(String[] args) {
        // 7-10 ~ 7-11 참조변수 super, 생성자 super()

        // 참조변수 super : 객체 자신을 가리키는 참조변수, 인스턴스 메서드 내에서만 존재한다.
        // 조상의 멤버를 자신의 멤버와 구별할 때 사용한다. / iv와 lv를 구별할 때 사용하는 참조변수 this를 생각하면 쉽다.
        // 생성자 super() : 조상의 생성자를 호출할 때 사용한다.
        // 생성자와 초기화 블럭에는 상속이 안된다.
        Child c = new Child(1, 2, 3);

        System.out.println(c.x); // 메서드 호출 전 10 / 호출한 후로 코드 순서를 변경 후 20
        c.Cmethod();

        // 생성자 첫줄에 생성자 호출이 없으면 컴파일러가 자동으로 super();를 삽입하지만 기본 생성자를 호출할 때는 에러가 날 수 있다.
        System.out.println("중요! 별⭐️⭐️⭐️ :생성자의 첫 줄에는 반드시 생성자를 호출해야 한다.");
    }
}

class Parent {
    int x;

    Parent(int x, int y) {
        this.x = 10;
    }
} // class의 끝

class Child extends Parent {
    int y = 10;
    int z = 5;

    Child (int x, int y, int z) {
        // this.x = 20; 자손 생성자는 조상의 생성자를 초기화 하면 안된다.
        super(x, y); // 올바른 방법 : super() 호출
        this.z = 3; // 자기 자신의 것은 초기화 가능
    }

    void Cmethod() {
        super.x = 20;
        System.out.println(super.x);
    }
}

package javajungsuk7_10;

public class Ch07_12a14 {
    
    public static void main(String[] args) {
        // 7-12 ~ 7-14 패키지, 클래스 패스

        // 패키지(폴더) : 서로 관련된 클래스의 묶음 / Java8 기준으로 약 4천개의 클래스가 있는데 그것을 관리하기 쉽게 만든 것이 패키지다.
        // 클래스(파일)
        // 클래스 패스(class path) : 클래스 파일의 위치를 알려주는 경로

        System.out.println("클래스의 실제 이름(full name)은 패키지를 포함한 것이다.");
        System.out.println("패키지는 소스파일의 첫 번째 문장으로 단 한번 선언한다.");
        System.out.println("같은 소스파일의 클래스들은 모두 같은 패키지에 속하게 되고, 패키지 선언이 없으면 이름없는 default 패키지에 속하게 된다.");
        System.out.println("환경변수(class path)로 관리하며 경로간의 구분자는 (세미콜론);을 사용한다."); // 환경변수에 (패키지 루트)경로를 등록하여 사용
    }
}

package javajungsuk7_10; // 패키지 선언

import static java.lang.Math.random;
// import static java.lang.Math.*;

public class Ch07_15a16 {
    
    public static void main(String[] args) {
        // 7-15 ~ 7-16 import문, static import문

        // iport : 컴파일러에게 클래스가 속한 패키지를 알려준다.
        // static import문 : static멤버를 사용할 때 클래스 이름을 생략하고 쓸 수 있다. / 코드가 길어지면 더 간단하게 쓰기 위해 만든 것이다.
        // import 패키지명.클래스명; : 더 명확하게 알 수 있는 장점이 있다. / import 패키지명.*; : 그 패키지에 속한 모든 클래스를 쓸 수 있는 장점이 있다.
        // 선언 : 패키지문과 클래스 선언의 사이에 선언을 해야한다.

        System.out.println("import 단축키 : 윈도우 기준 control + shift + o(알파벳)");
        System.out.println("java.lang 패키지(기본 패키지)의 클래스는 import를 하지 않고도 사용이 가능하다.");
        System.out.println(random()); // static import문으로 클래스 이름을 생략가능하게 하여 random()으로 사용할 수 있게 했다.
    }
}

package javajungsuk7_10;

public class Ch07_17a20 {
    
    public static void main(String[] args) {
        // 7-17 ~ 7-20 제어자, static, final, abstract

        // 제어자(modifier) : 클래스와 클래스의 멤버에 부가적인 의미 부여 / 형용사 + 명사를 생각하면 쉽다.
        // 접근 제어자는 다음 7-21에서 설명

        System.out.println("하나의 대상에 여러 제어자를 같이 사용가능하다. / '접근 제어자'는 4개 중 하나만 사용가능하다.");
        System.out.println("제어자의 순서는 상관없지만 관례적으로는 접근 제어자를 가장 왼쪽에 쓴다."); // final보다는 static을 더 먼저 쓴다.

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

// static : 클래스의, 공통적인
class StaticTest {
    static int iv = 3; // 명시적 초기화 / 인스턴스 변수(iv) + static = static(클래스) 변수 cv가 된다.

    static {} // 복잡 초기화

    static int max(int a, int b) { // 객체 생성 x / 객체 생성이 필요한 인스턴스 멤버 사용불가
        return a > b ? a : b;
    }
} // class의 끝

// final : 마지막의, 변경될 수 없는
final class FinalTest { // 조상이 될 수 없는 마지막 클래스
    final int MAX = 100; // 상수 : 값을 변경할 수 없는 변수

    // final void getMaxSize() { // 오버라이딩을 할 수 없는 메서드(변경불가)
    //     final int Lv = MAX; // 값을 변경할 수 없는 지역변수(상수)
    //     return MAX;
    // }
} // class의 끝

// abstract : 추상의, 미완성의
abstract class AbstractTest { // 추상 클래스 : 미완성된 클래스 >> 미완성된 메서드를 포함한 클래스를 말하는 것
    abstract void move(); // 추상 메서드 : 미완성된 메서드 >> 선언부는 있지만 구현부{}는 없는 메서드를 말하는 것
} // class의 끝

package javajungsuk7_10;

public class Ch07_21 {
    
    public static void main(String[] args) {
        // 7-21 접근 제어자

        // 접근 제어자(access modifier) 4가지 : public, protected, default,  private

        // 접근 제어 가능 위치
        System.out.println("public : 접근 제한 X");
        System.out.println("protected : 같은 패키지 + (다른 패키지)자손");
        System.out.println("default : 같은 패키지");
        System.out.println("private : 같은 클래스");

        Test t = new Test();

        // 접근 제어자 확인
        System.out.println(t.pub); // 접근 제한이 없다.
        System.out.println(t.prt); // 같은 패키지 + 다른패키지의 자손까지 허용하고 다른 패키지에서 자손이 아닌 상속범위를 벗어난 클래스에서는 사용이 불가하다.
        System.out.println(t.dft); // 다른 패키지에서는 사용이 불가하다.
        // System.out.println(t.prv); // 같은 클래스 내에서만 사용가능한 접근 제어자라서 에러가 난다.
    }
}

class Test {
    public String pub = "public";
    protected String prt = "protected";
    String dft = "default";
    private String prv = "private";

    public void test1() {
        System.out.println(pub);
        System.out.println(prt);
        System.out.println(dft);
        System.out.println(prv);
    }
}