[24.09.25] TIL

yy·2024년 9월 24일

개발일지

목록 보기
109/122

JAVA 공부중

상속

  • 중복 줄어들고, 편리한 확장이 가능함.

  • 상속된 상태에서 자식클래스를 호출하면 메모리 구조가 자식 객체 안에 부모와 자식 둘 다 존재한다.

  • 상속관계에서 객체를 생성하면 내부에는 부모와 자식 모두 생성됨.

  • 상속관계의 객체를 호출할 때 대상 타입을 정해야함. 이때 호출자의 타입을 통해 대상 타입을 찾는다.
    ( 자식 타입으로 객체를 호출 후 메서드 실행 시 자식 타입에서 해당 메서드가 있는지 확인 후 없으면 부모 타입에서 해당 메서드를 찾는다. 부모에도 없으면 그 부모로 계속 올라가면서 찾는데 없으면 컴파일 오류 발생.)



메서드 오버라이딩(Overriding)

  • 부모 타입의 기능을 자식에서 다시 재정의하는 것.
  • 메서드 이름 같게, 내용은 다르게, @Override 애노테이션 넣기

메서드 오버라이딩 조건

  • 메서드 이름 동일해야함
  • 메서드 매개변수(파라미터)(순서, 타입, 개수 동일해야함), 반환 타입 동일
  • 생성자 오버라이딩 불가
  • 접근 제어자: 상위보다 제한적이면 안됨.(부모가 protected이면 자식은 public, protected가능하지만, private, default로 오버라이딩 불가)
  • static, final, private 키워드가 붙은 메서드 오버라이딩 불가
    • static: 클래스 레벨에서 작동. 인스턴스 레벨에서 사용하는 오버라이딩 노의미
    • final: 메서드 재정의 금지
    • private : 해당 클래스에서만 접근 가능하기때문에 자식 클래스에서 접근 불가.

package extends1.access.parent; 

public class Parent {
	public int publicValue; 
    protected int protectedValue; 
    int defaultValue;
    private int privateValue; 

    public void publicMethod() {
        System.out.println("Parent.publicMethod");     
        }

    protected void protectedMethod() {
        System.out.println("Parent.protectedMethod");     
        }

    void defaultMethod() {
        System.out.println("Parent.defaultMethod");     
        }

    private void privateMethod() {
        System.out.println("Parent.privateMethod");     
        }

    public void printParent() {
        System.out.println("==Parent 메서드 안==");
        System.out.println("publicValue = " + publicValue);
        System.out.println("protectedValue = " + protectedValue);
        System.out.println("defaultValue = " + defaultValue); //부모 메서드 안에서 접근 가능
        System.out.println("privateValue = " + privateValue); //부모 메서드 안에서 접근 가능
        //부모 메서드 안에서 모두 접근 가능 
        defaultMethod(); 
        privateMethod();
        } 
}
package extends1.access.child;

import extends1.access.parent.Parent;

public class Child extends Parent {
        public void call() {
            publicValue = 1;
            protectedValue = 1; //상속 관계 or 같은 패키지
        	//defaultValue = 1; //다른 패키지 접근 불가, 컴파일 오류
            //privateValue = 1; //접근 불가, 컴파일 오류
        	publicMethod();
        	protectedMethod(); //상속 관계 or 같은 패키지
        	//defaultMethod(); //다른 패키지 접근 불가, 컴파일 오류
            //privateMethod(); //접근 불가, 컴파일 오류
        	
            printParent();//이건 컴파일 오류 안남. public이고, 부모클래스로 들어가서 다른 메서드를 실행한것이므로 오류 안남.
            }
}

super 부모참조

부모와 자식의 필드명이 같거나 메서드 오버라이딩 되어있으면 자식에서 부모의 필드, 메서드를 호출할 수 없음 -> super를 이용해서 부모를 참조할 수 있음.

package extends1.super1;

public class Parent {
    public String value = "parent";

    public void hello() {
        System.out.println("Parent.hello");
    }
}
package extends1.super1;

public class Child extends Parent {
    public String value = "child";

    @Override
    public void hello() {
        System.out.println("Child.hello");
    }

    public void call() {
        System.out.println("this value = " + this.value); //this 생략 가능 System.out.println("super value = " + super.value);
        this.hello(); //this 생략 가능 super.hello();
    }
}


super 생성자

  • 부모의 생성자가 없으면(혹은 매개변수가 없는 생성자가 있으면) super()만 자식 생성자 첫줄에 명시해주거나 생략이 가능.
  • 부모의 생성자가 정의가 되어있으면 자식 생성자안 첫줄에 매개변수를 넣은 super()를 명시해줘야함.
  • 생성자는 하나만 호출할 수 있음.
  • super는 꼭 한번은 호출되게 해야함.
package extends1.super2;

public class ClassA {
    public ClassA() {
        System.out.println("ClassA 생성자");
    }
}
package extends1.super2;

public class ClassB extends ClassA {
    public ClassB(int a) {
        super(); //기본 생성자 생략 가능
        System.out.println("ClassB 생성자 a=" + a);
    }

    public ClassB(int a, int b) {
        super(); //기본 생성자 생략 가능
        System.out.println("ClassB 생성자 a=" + a + " b=" + b);
    }
}
package extends1.super2;

public class ClassC extends ClassB {
    public ClassC() {
        super(10, 20);
        System.out.println("ClassC 생성자");
    }
}
package extends1.super2;

public class Super2Main {
    public static void main(String[] args) {
        ClassC classC = new ClassC();
        // 호출 하면 super를 타고 타고 올라가서 최상위 부모클래스부터 결과가 출력됨.
    }
}

코드를 변경하여 아래같이 this를 이용하더라도 결국 super를 타고 한번은 super를 호출해야함.


package extends1.super2;

public class ClassB extends ClassA {
    public ClassB(int a) {
        this(a, 0); //기본 생성자 생략 가능
        System.out.println("ClassB 생성자 a=" + a);
    }

    public ClassB(int a, int b) {
        super(); //기본 생성자 생략 가능
        System.out.println("ClassB 생성자 a=" + a + " b=" + b);
    }
}

final 클래스 : 상속 불가 ( 자식 클래스한테 상속 안시켜줌)

final 메서드 : 오버라이드 불가 ( 자식 클래스한테 오버라이드 안시켜줌)

profile
시간이 걸릴 뿐 내가 못할 건 없다.

0개의 댓글