본문 바로가기
java

22.11.09 상속, 생성자, final, super(), Override, Overload

by SoulMania 2023. 2. 13.

1109숙제.txt
0.00MB
221109.zip
0.04MB
221109_숙제.txt
0.00MB
Student01.java
0.00MB
Student01_Main.java
0.00MB
Sun01.java
0.00MB
Sun01_Main.java
0.00MB
단원설명.txt
0.00MB
설명.txt
0.04MB
송준호_1109_.txt
0.00MB

java.lanf 패키지의 Object 클래스는 최상위 클래스

원래는 ==나 equals메소드 둘다 번지비교이다.
String의 equals메소드는 형태 값 비교.. 번지수 주소지 비교가 아니라... 이것이 메소드 오버라이딩이라고 볼 수 있다.

//이 클래스는 학생관련 데이터와 기능을 가진 클래스이다.
/*메소드 재정의(@Override)

  • 부모 클래스의 상속 메소드 수정해 자식 클래스에서 재정의하는 것
  •  
  • 메소드 재정의 조건 (p.295~296)
  • 부모 클래스의 메소드와 동일한 시그니처 가져야 함
  •  
  • 접근 제한을 더 강하게 오버라이딩 불가
  • public을 default나 private으로 수정 불가
  • 반대로 default는 public 으로 수정 가능
  • 새로운 예외(Exception) throw 불가 (예외처리는 10장 참조)
  • @Override 어노테이션
  • 컴파일러에게 부모 클래스의 메소드 선언부와 동일한지 검사 지시
  • 정확한 메소드 재정의 위해 붙여주면 OK
  • 메소드 재정의 효과
  • 부모 메소드는 숨겨지는 효과 발생
  • 재정의된 자식 메소드 실행
  • /

접근제한자

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
default
패키지만 같으면 다 된다>!!!! 상속 관계 다 필요없고 패키지만 같으면 허용. 다르면 다 비허용

protected 패키지가 같으면 default와 동일, 다르면 자식이면 허용. 상속관계 허용
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
상위클래스(추상적)
하위클래스(구체적)

하위클래스 is 상위클래스 이다.
개는 동물이다.
닭은 동물이다. 등등등...

int a =10;
상위클래스=하위클래스

하위클래스 is 상위클래스 이다.
10은 a이다.

동물=사람

Animal animal = new Human();
Animal animal = new Student();
Animal animal = new Dog();
Animal animal = new Cat();

animal 이라는 참조변수는 다양한 형태를 가질 수 있다. == 다형성

Object동물

필드

  • 나이 int age = 20;
  • 키 int height = 180;
  • 몸무게 double weight = 77.7;
    메소드
  • 움직인다() 리턴유형 move(매개변수);
  • 잠을잔다() void sleep();
  • 먹는다() void eat(String anything);
  • 호흡한다() void breath(~~);
  • 소리낸다() 리턴유형 sound("멍멍")
  • 내장기관이 있다() boolean gut();

사람은 동물이다

Human is an animal.

-> is a 관계 => 상속관계
a = 10;
Animal = Human
Animal 참조변수 = new Human();

Animal{
int age; 등
void sleep(){} 등
}

class Human extends {
int age; 등등등
void sleep(){} 등+
@Override
sound(){"말을 한다"}
write()

}


package other;

/*접근제한자

  • public : 아무나 다 돼---> 접근을 안 막을게
  • protected : 동일패키지이거나, 다른패키지일때는 상속된 필드내에 선언된 자식클래스이면 가능.
  • --->동일 패키지 일때는 상속클래스필드 외부참조변수 선언으로 접근도 가능하면서 상속필드내에서 접근 가능. --->다른 패키지 일때는 상속클래스필드 외부 참조변수 선언으로 접근 불가, 상속필드 내에서만 접근가능. protected 접근 제한자 !!!!최종정리​!!! 상속과 관련된 접근 제한자​ 같은 패키지: default와 동일​ 다른 패키지: 자식 클래스만 접근 허용 (p.303~305) ​
  • default : 동일패키지내에서만 접근허용
  • private : 동일클래스 내에서만 접근 허용
  • /
    public class AccessModifier {
    //필드
    //접근제한자 [제어자] 데이터타입 필드명[=값];
    public int pub = 100;
    protected int pro = 200;private int pri = 400; //동일 클래스 안에서만 사용 가능
  • int pack = 300;//default 라는건 default를 적으라는게 아니라 아무것도 적지 말라는 의미.
void test() {
    pub=110; // 그냥 다 되는 것.
    pro=220; // 상속관계. 그냥 같은 클래스 안에 있으면 당연히 된다.
    pack=330; // --->default 이기 때문에 동일 패키지 내에 접근 및 변경 가능.
    pri=444; //--->동일클래스 안에 있으니 접근해서 데이터 변경까지 가능.
}

}



package ch06;

public class Member02 {
//field (인스턴스 필드)
//[접근제한자][제어자] 데이터타입 필드명[=값];
//static 필드(=정적필드)클래스 명을 통해서 접근한다!!! 그래서 클래스 필드라고도 한다. (대신 앞에 static이 붙는다.)
static String nation = "KOREA~"; //대한민국 사람만 있으므로 국적은 초기값으로 모두 동일하게 초기화 한다. (static field) 참조변수명이 없기 때문에 static이 붙는다고도 볼 수 있다.
//동일한 변수 값에 대해서 static 이라고 선언하면 객체를 굳이 만들지 않아도 접근가능하다!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

//인스턴스 필드  --->>> 인스턴스 변수, 즉 참조변수는 참조변수 명.필드데이터 이런식으로 접근을 해줘야한다. 참조변수명에 주소가 있으므로. (non-static field)
//field(인스턴스필드)
//[접근제한자][제어자] 
private String name; // 이름
private String id; // id
private String pwd; // 비번
private int age; // 나이

// 생성자
// [접제][제] 클래스명 (매개변수){}
// 기본생성자 - 매개변수없는 생성자
//==> new Member01();
Member02(){} // --> 기본 생성자(default constructor)
//매개변수 있는 생성자-주로 필드값을 초기화
Member02(String name, String id, String pwd, int age){ //생성자 오버로딩
this.name = name;
this.id = id;
this.pwd = pwd;
this.age = age;
}

Member02(String nation, String name, String id, String pwd, int age){ //생성자 오버로딩
    this.name = name;
    this.id = id;
    this.pwd = pwd;
    this.age = age;
}

// method
// [접근제한자][제어자] 리턴유형 메소드명(매개변수리스트){}

// 리턴유형 set필드명(타입 매개변수명->내가 변경하고자하는 필드명과 똑같이 한다.) {
// this.필드명=매개변수명;
// }

void setName(String name) {
    this.name=name;
}
void setId(String id) {
    this.id=id;
}
//pw, age값 변경하는 setter() 작성
void setPwd(String pwd) {
    this.pwd=pwd;
}
void setAge(int age) {
    this.age=age;
}

//따라서 필드 값의 private를 건드리는 것이 아니라 set메소드 앞에 접근제한자를 붙여 관리해준다.

// 리턴유형 get필드명() {
// return 필드명;
// }

String getName() {
    return name; //필드에 있는 값을 리턴 한다!!!!  this.name 인데 생략. 필드에 있는값.
}



String getId() {
return id; //필드에 있는 값을 리턴 한다!!!!  this.id 인데 생략. 필드에 있는값.
}

String getPwd() {
return pwd; //필드에 있는 값을 리턴 한다!!!!  this.pwd 인데 생략. 필드에 있는값.
}

int getAge() {
return age; //필드에 있는 값을 리턴 한다!!!!  this.pwd 인데 생략. 필드에 있는값.
}




public void test(){

}  

public void delete(){

}  

public void update(){

} 



void getInfo(){ //하나하나 get메소드를 만들지 말고 이런식으로 한번에 모아서 메소드 하나로 묶으면 한번에 다 출력한다.
    System.out.println("이름 : "+ this.name);
    System.out.println("아이디: "+ this.id);
    System.out.println("비번 : "+ this.pwd);
    System.out.println("나이 : "+ this.age);
    System.out.println("국가 : "+ this.nation);
    System.out.println();

}

}


package ch06;

public class Member02_Main {

//field

//constructor

//method

public static void main(String[] args) {
    //참조변수선언 및 Member02클래스 객체 생성

    Member02 member1 = new Member02();//기본생성자를 호출


    //private는 다이렉트로 필드로 접근하기보다 set메소드나 get메소드를 이용하여 접근하고 수정해주는것이 좋다.




    //setter()를 이용하여 필드값을 setting가능
    member1.setName("손흥민");


    //이름 확인
    String name1 = member1.getName();//필드로 바로 접근은 불가능 하지만 getter()를 통한 필드의 값을 가져올 수 있다.
    System.out.println(name1);
    //System.out.println(member2.getName());

    member1.setId("sid");

    //id 확인
    String id1 = member1.getId();
    System.out.println(id1);
    //System.out.println(member2.getId()); 

    member1.setPwd("s123");

    //pwd값 확인        
    String pwd1 = member1.getPwd();
    System.out.println(pwd1);
    //System.out.println(member2.getPwd()); 

    member1.setAge(31);

    //age값 확인
    int age1 = member1.getAge();
    System.out.println(age1);
    //System.out.println(member2.getAge()); 

    System.out.println("--------------------------------------------------------------------------");
    member1.getInfo(); //getInfo 메소드로 만들어서 한번에 출력

    System.out.println("--------------------------------------------------------------------------");


    //회원이름 출력
    //System.out.println(member1.name); ///-->> private라서 안보인다. name, id, pwd, age 등등... nation만 보인다.
    //The field Member02.name is not visible

    //매개변수가 있는 생성자를 이용하여 필드값을 setting가능
    Member02 member2 = new Member02("대한민국", "홍길동", "hid", "h123", 20);

// System.out.println(Member02.nation);
// System.out.println(member2.name); //변수에 직접적으로 접근이 안된다. 변수에 따로 담아 선언해도 마찬가지... 이럴때는 메소드로 선언해서 메소드를 호출해야한다.
//The field Member02.name is not visible
//데이터보호를 목적 접근제한 -> 캡슐화
System.out.println("--------------------------------------------------------------------------");

}

}


package other;

class Foo{
public static String classVar = "I class var";
public String instanceVar = "I instance var";
public static void classMethod() { //클래스 메소드에안에서는 클래스 변수에는 접근이 되는데 인스턴스 변수에는 접근할 수 없다.
System.out.println(classVar); //OK
// System.out.println(instanceVar); //Error
}

public void instanceMethod() { //인스턴스 메소드안에서는 클래스 변수와 인스턴스 변수 모두 접근 가능하다.
    System.out.println(classVar); //OK
    System.out.println(instanceVar); //OK
}

}
public class StaticApp {

public static void main(String[] args) { //클래스를 통해서는 클래스변수에 접근이 당연히 되고 인스턴스 변수에 접근 할 수 없다. 즉 인스턴스는 인스턴스를 통해서 사용하도록 고안된 변수다
    System.out.println(Foo.classVar); //OK

// System.out.println(Foo.instanceVar); //Error
Foo.classMethod(); // OK
// Foo.InstanceMethod(); // Error 인스턴스 메소드는 인스턴스 소속이기 때문에 클래스를 통해서 접근이 안된다.

    Foo f1 = new Foo(); //f1이라는 인스턴스 만듦
    Foo f2 = new Foo();
    //classVar는 스태틱이라 클래스 소속이고 f1에는 실제 값이 존재하지 않고 Foo 라고 하는 클래스를 가리키고 있는 것. 따라서 f1의 classVar 값을 바꾸면 Foo의 classVar 값이 바뀐다. 반대도 마찬가지. 서로 영향을 미친다.
    //instanceVar는 Foo에서 f1이라는 인스턴스가 생성될 때 instanceVar라고 하는 변수가 생성되면서 만약에 클래스의 값까지 세팅되어있다면 그 값까지 복제가 된다. 따라서 이것은 서로 링크가 걸려있지 않기 때문에 f1에서 instanceVar를 바꾼다고 해도 Foo의 instanceVar 값이 바뀌지 않는다. 서로 독립된 존재 
    //classMethod도 마찬가지로 f1에서 는 실제값이 없이 Foo 의 classMethod 값을 참조하고 있는 것.(가리키고 있는 것.)
    //instanceMethod도 Foo에서 f1이라는 인스턴스가 생성될 때 Foo에 있는 instanceMethod 라고 하는 메소드 똑같이 복제를 한다. 따라서 이것은 서로 링크가 걸려있지 않기 때문에 f1에서 instanceMethod를 바꾼다고 해도 Foo의 instanceMethod 값이 바뀌지 않는다. 서로 독립된 존재 


    System.out.println("--------------------------------------------------------------------"); 

    System.out.println(f1.classVar); // I class var -->
    System.out.println(f1.instanceVar); // I instance var

    f1.classVar = "changed by f1";
    System.out.println(Foo.classVar); // changed by f1
    System.out.println(f2.classVar); // changed by f1

    f1.instanceVar = "changed by f1";
    System.out.println(f1.instanceVar); // changed by f1
    System.out.println(f2.instanceVar); // I instance var


}

}


package ch06;

//이 클래스는 학생관련 데이터와 기능을 가진 클래스이다.
/*메소드 재정의(@Override)

  • 부모 클래스의 상속 메소드 수정해 자식 클래스에서 재정의하는 것
  •  
  • 메소드 재정의 조건 (p.295~296)
  • 부모 클래스의 메소드와 동일한 시그니처 가져야 함
  •  
  • 접근 제한을 더 강하게 오버라이딩 불가
  • public을 default나 private으로 수정 불가
  • 반대로 default는 public 으로 수정 가능
  • 새로운 예외(Exception) throw 불가 (예외처리는 10장 참조)
  • @Override 어노테이션
  • 컴파일러에게 부모 클래스의 메소드 선언부와 동일한지 검사 지시
  • 정확한 메소드 재정의 위해 붙여주면 OK
  • 메소드 재정의 효과
  • 부모 메소드는 숨겨지는 효과 발생
  • 재정의된 자식 메소드 실행
  • /

public class Student01_Answer extends Object {
//부모클래스로부터 상속받은 필드와 메소드가 존재한다.

//field
//[접근제한자][제어자] 데이터타입 필드명[=값];
private int     sno;        //학번
private String     major;        //전공
private int     grade;        //학년
private String     sname;        //이름
private char     gender;        //성별

//constructor
//[접근제한자][제어자]클래스명(매개변수리스트){}
//default constructor(=매개변수가 없는 생성자)
public Student01_Answer() {}

//매개변수가 있는 생성자
//주의. 매개변수가 있는 생성자만을 선언했을 경우
//외부에서 기본생성자를 호출할 수 있도록 하기위해서는
//명시적으로 기본생성자를 반드시 선언해야 한다.
public Student01_Answer(int sno, String major, int grade, String sname, char gender) {  //--->만약 기본생성자를 따로 선언 안하고 매개변수 생성자만 선언하면 다른 실행클래스나 외부 클래스에서 매개변수가 없는 기본 객체를 쓸 수 없다.!!!!!
    this.sno=sno;
    this.major=major;
    this.grade=grade;
    this.sname=sname;
    this.gender=gender;
}


//method
//[접근제한자][제어자]리턴유형 메소드명(매개변수리스트){}
/*[접근제한자] 리턴유형 set필드명(타입 매개변수){
     this.필드명=매개변수;
 * }
 */



public void setSno(int sno) {
    this.sno=sno;
}
public void setMajor(String major) {
    this.major=major;
}
public void setGrade(int grade) {
    this.grade=grade;
}
public void setSname(String sname) {
    this.sname=sname;
}
public void setGender(char gender) {
    this.gender=gender;
}

/*[접근제한자] 리턴유형 get필드명(매개변수리스트) {
 * return 필드명;
 *}

 */

public int getSno() {
    return sno;
}
public String getMajor() {
    return major;
}
public int getGrade() {
    return grade;
}
public String getSname() {
    return sname;
}
public char getGender() {
    return gender;
}



//toString() ---> 오버라이딩
//Object 클래스로부터 상속받은 toString()메소드를 재정의한 메소드-->>오버라이딩  : 밑에 재정의한 toString을 주석처리 하면 원래 오브젝트 소속 toString이 호출된다.
@Override //에너테이션????? 1. 알려주는 기능, 2. 그 기능을 쓸떄 조건이 있는데 조건을 준수하는 기능
public String toString() {
    return "[학번]="+sno+", [전공]="+major+", [학년]="+grade+", [이름]="+sname+", [성별]="+gender;
}

}


package ch06;

public class Student01_Answer_Main {

//field

//constructor

//method

public static void main(String[] args) {
    //참조변수선언 및 Member02클래스 객체 생성
    //참조변수 선언 및 객체생성(기본생성자이용)
    Student01_Answer st1 = new Student01_Answer();//기본생성자를 호출하는데 Student01_Answer에 기본생성자 선언을 안하면 에러가 난다.


    //setter를 호출하여 필드값 설정하기
    st1.setSno(220001);
    st1.setMajor("경영");
    st1.setGrade(1);
    st1.setSname("최경영");
    st1.setGender('남');

    //getter를 호출하여 필드값 가져오기
    System.out.println("학번 : "+st1.getSno());
    System.out.println("학번 : "+st1.getMajor());
    System.out.println("학번 : "+st1.getGrade());
    System.out.println("학번 : "+st1.getSname());
    System.out.println("학번 : "+st1.getGender());


    System.out.println("--------------------------------------------------------------------------");

    //참조변수 선언 및 객체 생성(매개변수가 있는 생성자 이용)
    Student01_Answer st2 = new Student01_Answer(220002, "컴공", 2, "강컴공", '여');//기본생성자를 호출
    System.out.println( st2.getSno() ); 
    System.out.println( st2.getMajor() ); 
    System.out.println( st2.getGrade() ); 
    System.out.println( st2.getSname() ); 
    System.out.println( st2.getGender() ); 
    System.out.println("--------------------------------------------------------------------------");
    Student01_Answer st3 = new Student01_Answer(220003, "국어국문", 3, "세종대왕", '남');//기본생성자를 호출
    System.out.println( st3.getSno() ); 
    System.out.println( st3.getMajor() ); 
    System.out.println( st3.getGrade() ); 
    System.out.println( st3.getSname() ); 
    System.out.println( st3.getGender() ); 


    System.out.println("--------------------------------------------------------------------------");
    System.out.println("- Student01_AnSwer클래스의 toString()호출");
    System.out.println();
    //출력할 수 있는 명령문이 없으므로 println안에 써줘서 출력해줘야 한다.
    System.out.println(st1.toString());
    System.out.println();
    System.out.println(st2.toString());
    System.out.println();
    System.out.println(st3.toString());

    System.out.println("--------------------------------------------------------------------------");
    //변수안에 담아서 간소화

// Student01_Answer info;
// info = st1;
String stInfo1 = st1.toString();
String stInfo2 = st2.toString();
String stInfo3 = st3.toString();
System.out.println(stInfo1);
System.out.println();
System.out.println(stInfo2);
System.out.println();
System.out.println(stInfo3);

}

}


package ch07;

class GrandFather01 {
//필드
int aaa = 111;
//생성자
GrandFather01(){
System.out.println("GrandFather01()-기본생성자호출");
}
GrandFather01(int a){ //--->생성자 오버로딩
System.out.println("GrandFather01(int)-int 1개인 생성자");
}
//메소드
void testGF() {
System.out.println("GrandFather01의 () - 호출");
}

}

class Father01 extends GrandFather01{//extends Object{ 기본적으로 이렇게 되어있으나 부모클래스를 바꾸려면 명시해야한다. //The public type Father01 must be defined in its own file
////하나의 자바소스 안에 public은 하나만 존재 따라서 Father 클래스에는 public으로 선언할 수 없다.

    //필드
    int aa = 11;
    //생성자
    Father01(){
        System.out.println("Father01()-기본생성자호출");
    }

    Father01(int a){ //--->생성자 오버로딩
        super(1); //밑에 son01에서 super(1)매개변수가 있으므로 Father01(int a)인 생성자가 호출되고 그다음에 또 super(1)를 만나 GrandFather01(int a) 생성자를 호출한다.
                    //이런식으로 되면 son01_Main에서 son01 기본생성자만 호출해도 아래와 같이 출력 된다.
        //====================================================================================
                            //            GrandFather01(int)-int 1개인 생성자
                            //            Father01(int)-int 1개인 생성자
                            //            Sun01()-기본생성자호출
        //====================================================================================
        System.out.println("Father01(int)-int 1개인 생성자");
    }
    //메소드    
    void testF() {
        System.out.println("Father01의 () - 호출"); 
        super.testGF();
    }

}

public class Son01 extends Father01 {

    //필드
    int a = 1;
    //생성자
    Son01(){

        super(1); // son은 객체생성시 매개변수가 없으므로 기본 생성자가 호출되고 그다음에 super(1)를 만나 Father01(int a) 생성자를 호출한다.

        //부모클래스 객체 생성부터 진행. 객체 생성하려면 부모클래스가 가진 기본생성자 호출.
        //super();//부모클래스 생성자 호출 
        //-->부모생성자를 호출해주는 메소드  --> 생성자 안에서만 사용가능하고 생성자 첫줄에만 사용가능. 이것은 this()도 동일

        //그러나 위에 super();가 없어도 상위클래스 객체부터 만들라고 하는super();가 자동으로 호출되어지면서 Father01 객체부터 만들고 주소를 찍는다.
        System.out.println("Sun01()-기본생성자호출");

// super();
//반드시 첫 번째 줄에서 호출해야하는데 첫번째 줄이 아니기 때문에 호출X
//Constructor call must be the first statement in a constructor
}

// this 와 this()는 다름
// this: 자신클래스의 객체를 가르키는 참조변수
// this()는 동일클래스내에 또 다른 생성자를 호출
// this()사용시 주의할 점? 생성자 내에서만 사용가능하며 무조건 생성자 첫줄에서만 사용해야한다.

    //메소드

    void test() {
        System.out.println("super.aa="+super.aa);//부모의 필드에 접근 -->자식이 부모 필드에 데이터에 접근 가능
        super.testF();

// super(); //
//super();//부모클래스 생성자호출
//생성자안에서 호출해야 하는데 일반메소드내에서 호출하여 X
//Constructor call must be the first statement in a constructor
}

}


package ch07;

public class Son01_Main {

public static void main(String[] args) {
    //아들 객체 생성
    Son01 son1 = new Son01();
    System.out.println(son1);
    son1.test();    //---->얘 하나만 호출했는데도 아래 부모 클래스 들이 호출됨. super.을 걸었기 때문
    /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
        super.aa=11                    아들 클래스내에 메소드 프린트 문 실행하고     아버지 클래스 메소드로 이동    
        Father01의 () - 호출            아버지 클래스 내에 메소드 testF()에서 프린트문 찍고  할아버지 클래스 메소드로 이동
        GrandFather01의 () - 호출        할아버지 클래스 내에 메소드 testGF()에서 프린트문 찍고 종료
    &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& */


    /*
    Father01()-기본생성자호출   --->상속관계 이므로 ...하위클래스 아들 객체만 생성해도 아버지 기본 생성자 까지 호출 된다. 
                Sun01에 아들 생성자 안에 그러나 super();가 없어도 상위클래스 객체부터 만들라고 하는super();가 자동으로 호출되어지면서 Father01 객체부터 만들고 주소를 찍는다.
    Sun01()-기본생성자호출
    ch07.Sun01@15db9742


    GrandFather01 까지 아버지 클래스의 부모로 걸면

    자식객체만 생성해도 할아버지 클래스 객체까지 생성하여 호출한다. 할아버지 클래스 기본생성자 호출

     */

    System.out.println("----------------------------------------------------------------"); 
    //Son01 son2 = new Son01(222);

    System.out.println(son1.aa); //--->아들 클래스에 extends Father01을 지우면 에러남!!!
    System.out.println(son1.aaa); //--->아버지 클래스에 extends GraFather01을 지우면 에러남!!!

}

}


package ch07;

/*final 키워드의 용도​
-final 필드: 수정 불가 필드​
-final 클래스: 부모로 사용 불가한 클래스​
-final 메소드: 자식이 재정의할 수 없는 메소드​

*상속할 수 없는 final 클래스​
-자식 클래스 만들지 못하도록 final 클래스로 생성​

​*오버라이딩 불가한 final 메소드​
-자식 클래스가 재정의 못하도록 부모 클래스의 메소드를 final로 생성​ */

//상속할 수 없는 final 클래스
final class Father02 {
}

//class son02 extends Father02 { //final 이 붙은 클래스로부터 상속 받을 수 없다!
//son02클래스는 Father02클래스의 subclass(=자식클래스=하위클래스)클래스가 될 수 없다.
//The type son02 cannot subclass the final class Father02
//}

public class Mother01 {
//필드
int a = 11;
final int b = 22; //final 필드 : 수정 불가 필드 // a = 111; -->필드영역에 선언만 되고 값수정은 안된다.

//생성자
//메소드
void testM1() {
    a = 111;

// b = 222; //---> 위에 필드에 final int b 라고 final을 추가 하는순간 에러가 난다.
System.out.println(b); //프린트문 같이 접근은 허용 하지만 위처럼 값 수정은 안돼!!!!
//Mother01 클래스에 포함된 필드B는 final 필드이므로 222라는 값으로 수정 불가. ★중요한 값을 final로 처리한다.
//The final field Mother01.b cannot be assigned

    System.out.println("Mother01의 testM1()");
}

// -final 메소드: 자식이 재정의할 수 없는 메소드
final void testM2() {
System.out.println("Mother01의 testM2()");
}

public static void main(String[] args) { ///오버라이딩 된 값 출력 해보려면 메인메소드 작성 필요!!!

    Daughter d1 = new Daughter();
    d1.testM1();
    d1.testM2();
    System.out.println("-----------------------------------------------------");
}

}

class Daughter extends Mother01{
//필드
//생성자
//메소드

void testD1() {}

//Mother클래스로부터 상속받은 testM1()을 오버라이드 하세요
//@Override
//private void testM1() {}//원래 부모 것 오버라이딩 할때 기본 default면 그것보다 더 넓은 개념의 접근제한자 또는 같은 접근 제한자만 가능... 
//Mother01클래스로부터 상속받은 접근제한을 줄일 수 없기 때문에 에러 발생
//Cannot reduce the visibility of the inherited method from Mother01
/*접근제한을 더 강하게 오버라이딩 불가
 * public을 protected, default나 private으로 수정불가
 * 반대로 default는 protected나 public으로 수정가능*/

@Override
void testM1() {         
    System.out.println( super.a );
    System.out.println( super.b );
    super.testM2(); //--->호출해서 출력은 되는데 final이라 수정이나 변경은 안된다.
}


//Mother클래스로부터 상속받은 testM2()을 오버라이드 하세요
//@Override

// void testM2() {} //final 붙어서 오버라이드 할 수 없다.!!!!!!
//Mother01클래스로 부터 상속받은 final메소드는 오버라이드 할 수 없다.
//Cannot override the final method from Mother01

}


package ch07;

public class Machine {

int price; //가격
String performance; // "상", "중", "하"
char grade; //등급 A, B, C
String size; //"대", "중", "소";
double weight; //무게
boolean state1; //전기를 먹는 기계인지 아닌지 상태값 리턴 변수
boolean state2; //기름을 먹는 기계인지 아닌지 상태값 리턴 변수



void operation(){
    System.out.println("기계가 가동중이다.");
}

void sound(){
    System.out.println("소리가 난다.");
}

void isElectro(){
    if(this.state1) {    
    System.out.println("전기를 소모하는 기계입니다.");
    }else {
    System.out.println("전기를 소모하는 기계가 아닙니다..");
    }
}

//
void isOil(){
if(this.state2) {
System.out.println("기름을 소모하는 기계입니다.");
}else {
System.out.println("기름을 소모하는 기계가 아닙니다.");
}

}

}



package ch07;

public class Computer extends Machine {

String cpu = "intel core i7 코피레이크";
String manYmd = "2022-02-15";
String memory = "8GB"; // 8GB 16GB등등
String performance = "중"; //"상", "중", "하"



Computer(int price){
    this.price=price;

// System.out.println("가격은"+this.price+"이다.");
}

void plugIn() {
    super.state1=true;
}
void plugOut() {
    super.state1=false;
}

void oilIn() {
    super.state2=true;
}
void oilOut() {
    super.state2=false;
}


@Override
void operation(){
    if(state1) {
        System.out.println("컴퓨터가 가동중입니다.");
    }else {
        System.out.println("컴퓨터가 가동중이 아닙니다.");
    }
}

// void isOil(boolean state2){
// if(state2) {
// System.out.println("기름을 먹습니다.");
// }else {
// System.out.println("기름을 안먹습니다.");
// }

public static void main(String[] args) {

    Computer cp = new Computer(4000000);
    System.out.println("가격은"+cp.price+"이다.");
    cp.plugIn();
    cp.operation();
    cp.isElectro();
    cp.oilOut();
    cp.isOil();
    cp.sound();






}

}