٩(๑•̀o•́๑)و

20200304 본문

Java

20200304

11mia 2020. 3. 5. 00:50

클래스에서 상속(inheritance)의 의미

  • 새로운 클래스를 정의할 때 이미 구현된 클래스를 상속받아서 속성이나 기능이 확장되는 클래스를 구현함 -> 객체지향언어의 특징
  • A라는 클래스보다 기능이 조금 더 확장된 유사한 클래스를 정의할 경우 A를 상속받아서 구현하면됨
  • 코드의 재사용성 향상. 단 이때, 기존에 있던 클래스와 유사하되 조금더 확장된 클래스일 경우 사용. 이질적인 클래스간에는 상속을 사용해선 안됨
  • 상속하는 클래스 : 상위클래스=parent class = base class = super class
  • 상속받는 클래스 : 하위클래스=child class = derived class = subclass
  • 클래스 정의시 extends 키워드 사용
  • 자바에서 extends 뒤에는 딱 1개의 클래스명만 적을 수 있다. 즉 single inheritance만을 허용. (다중상속 허용하지 않음)
  • 다이어그램에서는 하위->상위 방향으로 화살표
  • 상위 클래스는 하위 클래스보다 일반적인 개념과 기능을 가짐. 하위 클래스는 상위 클래스보다 구체적인 개념과 기능을 가짐
  • 하위 클래스에서 상위 클래스의 멤버변수에 직접 접근이 가능하려면 상위 클래스에서 protected 혹은 public으로 정의되어야함

 

하위 클래스가 생성되는 과정

  • 하위 클래스가 생성될 때 상위 클래스가 먼저 생성됨
  • 상위 클래스의 생성자가 호출되고 하위 클래스의 생성자가 호출됨
  • 하위 클래스의 생성자에서는 무조건 상위 클래스의 생성자가 먼저 호출되어야함.
  • 하위 클래스에서 상위클래스의 생성자를 호출하는 코드가 없는 경우 컴파일러는 상위 클래스 기본 생성자를 호출하기 위한 super()를 추가
  • super는 상위 클래스의 메모리 위치(참조값)을 가지고있음 (cf. this는 자기자신의 메모리를 의미). this()로 다른 생성자를 호출하듯 super()를 통하여 상위 클래스의 디폴트 생성자를 호출할 수 있다.
  • super()로 호출되는 생성자는 상위 클래스의 기본 생성자임
  • 만약 상위 클래스의 기본 생성자가 없는 경우(매개 변수가 있는 생성자만 존재하는 경우. 이 경우에는 컴파일러가 기본생성자를 추가하지 않음) 하위 클래스에서 명시적으로 상위 클래스의 매개변수가 있는 생성자를 호출해야함
  • 상위클래스에 기본생성자가 명시적으로 존재하거나 컴파일러에 의해 추가될 수 있는 경우에는 문제가 되지 않음.
  • 이렇게 해야 하위 클래스만 생성하여도 상위 클래스에서 상속받은 모든 것들을 사용할 수 있음. 상위클래스의 속성을 사용할 수 있다는 의미는 상위 클래스의 속성이 힙메모리에 생성되어있다는 의미이기때문.

 

상속에서의 메모리 상태

  • 상위 클래스의 인스턴스가 먼저 생성되고, 하위 클래스의 인스턴스가 생성됨.
  • 하위 클래스의 생성자 호출-> 가장 먼저 super()에 의한 상위 클래스 생성자 호출->상위 클래스의 인스턴스 즉 상속되어지는 멤버변수들이 힙메모리에 생성 -> 하위클래스에만 존재하는 멤버변수들이 추가로 생성됨
  • 하위클래스에서 super가 가리키는 위치는 상위 클래스의 인스턴스들이 메모리 위치값.

 

상위 클래스로의 묵시적(암시적) 형 변환(업캐스팅)

  • 상위클래스type 변수 = new 하위클래스type();
  • 상위 클래스type으로 변수를 선언하고 하위 클래스 인스턴스를 생성할 수 있음.
  • 하위 클래스는 상위 클래스의 타입을 내포하고 있으므로(상속받았기때문), 상위 클래스로 묵시적 형변환이 가능함.
  • 상속관계에서 모든 하위 클래스는 상위 클래스로의 묵시적 형 변환이 됨.(특별히 뭔가를 해주지않아도 자동으로 변환됨)
  • 하위 클래스의 타입은 상위 클래스의 변수 타입으로 자동 형변환이 된다 = 업캐스팅
  • 그 역은 성립하지 않음. 하위클래스 = new 상위클래스()는 성립할 수 없음. 하위클래스가 상위 클래스보다 더 확장된 개념이기때문
  • 상위클래스type 변수 = new 하위클래스type(); 통하여 하위클래스의 생성자를 호출 -> 상위클래스의 인스턴스, 하위클래스의 인스턴스는 모두 생성이 되었으나, 상위클래스type변수가 접근할 있는 변수나 매개변수는 차이가 있다. 상위클래스type 변수는 상위클래스의 변수, 메서드에만 접근이 가능하다.(상위클래스 type이기때문) 하위클래스에서 확장된 변수, 메서드에는 접근이 불가.

오버라이딩(overriding)

  • 상위 클래스에 정의된 메서드의 구현 내용이 하위 클래스에서 구현할 내용과 맞지 않는 경우 하위 클래스에서 동일한 이름의 메서드를 재정의 할 수 있음. 선언부는 동일하되 바디의 구현부가 다름
  • 재정의하려는 메서드의 선언부를 동일하게 하여 하위클래스에서 바디를 다시 정의해주면됨. 이때 선언부 위에 Override annotation(@Override)를 붙여줘야함. 컴파일러에게 오버라이딩됨(재정의된 메서드)을 알려줌
  • @Override를 쓴 후 상위 클래스에 선언된 선언부와 다른 메서드를 정의할 경우 에러발생

 

Annotation : 컴파일러에게 특정한 정보를 제공해주는 역할.

Annotation description

@Override

재정의된 메서드라는 정보 제공

@FunctionalInterface

함수형 인터페이스라는 정보 제공

@Deprecated

이후 버전에서 사용되지 않을 있는 변수, 메서드에 사용됨

@SuppressWarnings

특정 경고가 나타나지 않도록함.

(ex. @SuppressWarnings(“deprecation”) : @Deprecated 나타나지 않도록함)

 

형 변환과 오버라이딩 메서드 호출

-> 상위클래스 var = new 하위클래스(); var.method1();

위 코드에서 method1() 은? (재정의되었다고 가정하에)

-> 자바에서는 항상 인스턴스(하위클래스)의 메서드가 호출됨. 

==> 가상함수.

-> 자바는 기본적으로 모든 메서드가 가상메서드!

가상메서드(virtual method)

  • 메서드의 이름과 메서드 주소를 가진 가상 메서드 테이블에서 호출될 메서드의 주소를 참조함
  • 메서드보다 함수가 더 큰 개념. 메서드는 객제 지향 언어에서 멤버함수를 의미.
  • 메서드의 이름은 컴파일되면 그 자체로 주소가됨. 따라서 같은 이름의 메서드는 존재하지 않음. (메서드의 이름이 같음은 같은 주소라는 의미이기때문)
  • 오버로딩된 메서드들은 컴파일이될 때 매개변수의 타입에 따라 메서드명이 조금씩 달라진다
  • 메서드에 대해 맵핑되는 주소값이 따로있음. 메서드가 수행하는 코드의 위치를 갖고있어야하기때문.(해당 위치로 제어가 넘어가야함) 이 주소를 갖고있는 맵핑테이블이 있는데 이게 바로 가상 메서드 테이블.
  • 하위클래스에서 오버라이딩된 메소드는 상위클래스의 메소드와 다른 주소를 갖게됨
  • 하위클래스에서 오버라이딩되지 않은 메서드는 상위클래스의 메서드와 동일한 주소를 가진다.
  • 따라서 재정의된 메서드는 맵핑되는 주소가 각각있다.
  • 실질적으로 호출되는 메서드는 타입에 기반한 것이 아닌 생성된 인스턴스에 기반하여 호출되는 것이 기본!!

==> 각 메서드들의 맵핑되는 주소를 관리하는 가상함수 테이블이 있고 여기의 어드레스 맵핑에 의하여 호출이 되기때문에 발생하는 현상

==> 상위클래스 var = new 하위클래스();  var.method1();

의 예제에서는 

  1. method1 재정의가  경우 : 위클래스에 의하여 생성된 인스턴스이기때문에 재정의된 method1 호출된다.
  2. method1 재정의가 되지 않은 경우 : 상위클래스에 정의된 method1 호출된다.

Employee.getSalary()를 subClass인 PartTimer에서 재정의한 경우

 

Employee.getSalary()를 subClass인 PartTimer에서 재정의하지 않은 경우

 

'Java' 카테고리의 다른 글

20200307 - 인터페이스  (0) 2020.03.07
20200306  (0) 2020.03.06
20200305  (0) 2020.03.06
20200303  (0) 2020.03.03
20200301  (0) 2020.03.01