상속

진주원(JooWon Jin)·2024년 1월 10일
0

Java

목록 보기
2/3
post-thumbnail

객체지향 프로그래밍의 특징

  • Abstraction (추상화)
  • Polymorphism (다형성)
  • Inheritance (상속)
  • Encapsulation (캡슐화)

우리는 자동차라는 클래스를 생성했다. 근데 ‘소나타’ 라는 새로운 클래스를 작성해야 한다 가정하자. 소나타는 자동차가 가지고 있는 모든 정보를 가지고 있다. 우리는 과연 전부 새로운 코드로 작성한 ‘소나타’ 클래스를 만들어야 할까?

상속

  • 객체지향 프로그래밍의 가장 큰 특징 중 하나인 상속은 기존의 클래스를 바탕으로 새로운 클래스를 작성하는 것
    • 상속을 통해 부모 클래스는 자식 클래스에게 멤버(변수 , 메서드) + 타입을 물려준다.
  • 상속을 통해 코드의 공통 관리가 가능하여 추가와 변경이 용이하다.
  • 재사용성이 향상되고 중복된 코드가 제거되기 때문에 유지보수에 용이하다.
  • 확장성 증가

슈퍼 & 서브

  • 조상, 슈퍼 클래스 : 상속을 해주는 대상 클래스
  • 자식, 서브 클래스 : 상속을 받는 대상 클래스
class SubClass extends SuperClass{} // 상속은 extends 연산자를 사용한다.

상속의 특징

  • 상속의 방향성 (부모 → 자식)

조상 클래스가 변경된다면 자식 클래스에도 자동적으로 영향 , But 자식 클래스의 변경은 조상 클래스에게 영향이 없다.

  • 멤버와 타입의 상속
    • 상속은 멤버(변수와 메서드)와 타입을 물려준다. (생성자와 초기화 블럭은 상속의 대상이 아닌다.)
  • 단일 상속
    • C++은 하나의 클래스가 여러 조상 클래스로부터 상속 가능한 다중 상속을 지원한다.
    • 하지만 자바에서는 오직 하나의 조상 클래스로부터만 상속이 가능한 단일 상속을 지원한다.
class LgTv{
	int price;
}

class ApplceTv{
	int price;
}

class MyTv extends LgTv,AppleTv{
 // ???? price 변수를 누구로부터 상속받아야 하지?
}

위 예시에서 MyTv라는 클래스는 LgTv, AppleTv 2개의 조상 클래스를 가지고 있다. 과연 이런 상황에서 MyTv의 price 변수는 어떤 클래스로부터 상속받아야 할까?

  • 위와 같은 상황이 다중 상속의 문제점이다. 자바는 이러한 고민거리를 해결하는 방법으로 다중 상속을 그냥 포기했다….
    • 뒤에서 배우겠지만 인터페이스의 존재로 어느정도 다중 상속의 장점을 채우고 있다.

Object Class - 클래스의 시조

여담으로 우리 모두 시조가 있다…(몇대손…) 클래스도 부모와 자식 관계가 있다면 시조도 존재하지 않겠는가? → Object Class (모든 클래스의 시조)

class MyClass{} -> class MyClass extends Object{}
  • 아무런 상속 관계를 지정하지 않을 경우 컴파일러는 자동적으로 컴파일 시 ‘extends Object’를 추가하여 컴파일한다.
    • 대표적으로 equals() , toString() 메소드가 바로 Object 클래스로부터 상속받는 것이다.

부모와 자식 관계는 지정하지만 클래스간 형제 관계라는 용어는 없다. 그 이유가 바로 이 Object 클래스 때문이다. 결국 모든 클래스는 형제 클래스이기 때문이다….

오버라이딩 (Overriding)

class 자동차{
		void print(){
			System.out.println("자동차");
		}
}

class 람보르기니 extends 자동차{
		// 나의 조상 클래스가 '자동차'이지만 명색이 람보르기니인데 자동차로 불리는 건..... 
		//나만의 print() 메서드를 정의하고 싶어
}
  • 조상 클래스로부터 상속 받은 메서드의 내용을 변경하는 것

오버라이딩 조건

메서드의 선언부가 일치해야 한다.

  • 메서드의 이름이 동일해야 한다.
  • 매개변수가 같아야 한다.
  • 반환 타입이 같아야 한다. (공변 반환 타입)
  1. 접근 제어자는 조상 클래스보다 좁은 범위로 변경할 수 없다.
    • public > protected > (default) > private
      • ex) 부모 클래스의 메서드의 접근 제어자가 public일 때 자식 클래스의 접근 제어자를 protected로 지정할 수 없다.
  2. 조상 클래스의 메서드보다 많은 수(넓은 범위)의 예외를 선언할 수 없다.

오버라이딩과 오버로딩

  • 명백히 다른 개념이라는 것을 알아야 한다.
    • 오버로딩 : 기존에 없는 메서드를 새로 정의하는 개념
    • 오버라이딩 : 기존의 메서드의 내용을 변경하는 것

공변 반환 타입

  • JDK 15에 추가된 개념
    • 반환 타입을 자식 클래스의 타입으로 지정할 수 있다.
    • 명시적 형변환을 외부에서 처리할 필요가 없다.
class Parent{
	Parent createOne(){ return Parent();}
}

class Child extends Parent{
	@Override
	Child createOne(){ return Child();} // 공변 반환 타입 사용하여 오버라이딩
}

super , super()

위에서 생성자는 상속 대상이 아니라고 했다.

super

  • 자손 클래스에서 부모 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조 변수
    • 속성과 메소드를 super.XX 형태로 호출 가능
    • 자손 클래스와 조상 클래스의 멤버가 중복 정의되어 서로 구별해야 하는 경우 사용 가능
  • super 역시 static 메서드에서는 사용 불가능

super()

  • 조상클래스의 생성자를 호출

상속이라는 것은 자손의 멤버와 조상의 멤버를 모두 합쳐 하나의 인스턴스가 생성된다. 이때 조상 클래스의 생성자가 호출되어야 하지만 기본적으로 생성자는 상속 대상이 아니다.

  • 자식 클래스의 생성자에서 조상 클래스의 생성자가 먼저 호출되어 조상의 멤버들이 먼저 초기화되어야 한다.
    • 자식 클래스 생성자에서 super()를 호출하지 않으면 컴파일러가 자동적으로 생성자의 첫줄에 삽입한다.
class Parent{
    int x;
    
    Parent(int x){
        this.x = x;
    }
}
class Child extends Parent{
    
    int y;
    
    Child(int y){
        this.y = y;
    }
}
  • 기본적으로 상속을 받기 위해서는 부모 클래스에 기본 생성자가 생성되어 있어야 한다.
    • 아니면 super()를 사용자가 추가해야 한다.
    • 컴파일러가 자동으로 자식 클래스에 super()를 호출하기 때문이다.
profile
Young , Wild , Free

0개의 댓글