상속

Sirius·2023년 11월 20일
post-thumbnail

1. 상속의 개념

객체지향 언어에서의 상속은 "유전적 상속" 과 유사하다.

  • Q 왜 상속이 필요할까?
    A 상속은 클래스 사이에 코드 중복을 제거하여 클래스를 간결하게 구현할 수 있게 해준다.(유지보수가 매우 편리함)
    -> 무조건 공통으로 들어가는 것을 부모 클래스로 두고 자식은 이거를 기반으로 계속 확장해 간다.

  • 상속의 장점
    1) 클래스 사이의 멤버 중복 선언 불필요
    -> 클래스의 간결화
    2) 클래스들의 계층적 분류로
    -> 클래스 관리 용이
    3) 클래스 재사용과 확장
    -> SW의 생산성 향상

2. 클래스 상속과 객체

1) 자바의 상속선언

자바에서는 extends 키워드를 사용하여 상속을 선언한다.

1> super class : 상속하는 부모 클래스
2> sub class : 상속받는 자식 클래스

class Point{
	int x, y;
}

class ColorPoint extends Point{
	String color,
    ...
}

2) 상속과 객체

서브 클래스에서 슈퍼클래스의 "private 멤버"로는 접근할 수 없다. 그 대신 private을 쓰는 슈퍼클래스의 메소드 등을 통해 접근할 수 있음

3) 자바 상속의 특징

가. 다중 상속 지원 X (C++과 다른점)

나. 모든 클래스는 Object 클래스를 자동으로 상속받도록 컴파일 됨

java.lang.Object는 유일하게 슈퍼 클래스를 가지지 않는 클래스이다.

4) 상속과 생성자

가. 서브클래스와 슈퍼 클래스의 생성자 호출 및 실행

서브 클래스의 객체가 생성될때, 서브클래스와 슈퍼클래스의 생성자 모두가 실행된다.(슈퍼 클래스의 생성자가 먼저 실행됨)

즉 "실행"은 슈퍼 클래스의 생성자가 먼저되고
"호출"은 서브클래스의 생성자가 먼저 된다.

나. 서브클래스에서 슈퍼 클래스 생성자 선택

1> 슈퍼클래스의 기본 생성자가 묵시적으로 선택

개발자의 명시적인 지시가 없는 경우이다.
이런 경우 슈퍼클래스의 생성자로 기본 생성자가 선택된다. (자바 컴파일러에 의해 묵시적으로 이루어짐)


-> 이 경우에는 서브클래스의 기본생성자를 보고 컴파일러가 자동으로 슈퍼클래스의 기본 생성자와 짝을 맞추었다.(짝이 있음)


-> 이 경우에는 클래스 B의 생성자와 짝을 이루는 기본 생성자가 A에 없다.(오류발생)


-> 이 경우에는 서브클래스의 매개변수가 있는 생성자도 슈퍼 클래스의 기본 생성자와 짝을 이루었다.

2. super()를 이용하여 명시적으로 슈퍼클래스의 생성자 선택

서브 클래스의 생성자에서 슈퍼 클래스의 생성자를 명시적으로 선택하는 것이 원칙이다.

5) 업캐스팅과 instanceof 연산자

캐스팅 : 타입변환

  • 클래스에 대한 캐스팅
    1) 업캐스팅 (서브클래스객체 -> 슈퍼클래스타입)
    2) 다운캐스팅

가. 업캐스팅 (Implicit Type Conversion)

-> Student 객체가 Person 타입으로 업캐스팅 되면, Person 클래스 객체로 취급된다. 또한 Student 클래스의 필드나 메소드는 접근할 수 없다.(자동으로 이루어짐: 자식은 부모의 성질을 모두 다 갖추었다.)

나. 다운캐스팅 (Explicit Type Conversion)

업캐스팅된것을 다시 원래대로 돌리는것(타입변환 지정해야함), 업캐스팅이 먼저 된 후에 다시 다운캐스팅이 가능하다.

Persoon p = new Student("이재문"); // 업캐스팅
Student s = (Student)p; // 다운캐스팅

다. instanceof 연산자와 객체 구별

업캐스팅을 여러번 한 경우 레퍼런스가 가리키는 객체의 클래스 타입을 구분하기 어렵다.

같은이름의 레퍼런스로 여러번 업캐스팅 해버리면 그 p가 가리키는 객체의 실제 클래스 타입이 뭔지 모른다.

Person p = new Person();
Person p = new Student();
Person p = new Professor();

instanceof는 이항연산자이다.
(객체레퍼런스) instanceof (클래스타입)

Person p = new Professor();
if(p instanceof Person) // true;
if(p instanceof Student) // false
if(p instanceof Researcher) //true
if(p instanceof Professor) //true

6) 메소드 오버라이딩

가. 메소드 오버라이딩의 개념

서브 클래스에서 슈퍼 클래스의 메소드를 중복 작성하여 슈퍼 클래스에 작성된 메소드를 무력화 시키고 객체 노릇을 하는 것이다.(이름, 리턴타입, 매개변수 리스트가 모두 같아야 함)

-> 슈퍼클래스의 레퍼런스를 이용하든 서브 클래스의 레퍼런스를 이용하든 항상 서브 클래스에 오버라이딩한 메소드가 실행된다.


-> 그림의 경우에 두번째에 A의 f()가 호출되었음에도 오버라이딩한 B의 f()가 실행된다.(동적 바인딩)

나. 오버라이딩의 목적, 다형성 실현

오버라이딩의 목적 : 슈퍼 클래스에 선언된 메소드를 동일한 이름으로 각 서브 클래스에서 필요한 내용으로 새로 구현하는데 있음

다형성 실현 : 오버라이딩은 상속을 통해 '하나의 인터페이스(같은 이름)에 서로 다른 내용 구현' 이라는 객체지향의 다형성을 실현하는 도구이다.

다. 동적 바인딩 사례

동적바인딩 : 실행할 메소드를 컴파일 시(compile time)에 결정하지 않고 실행 시(run time)에 결정하는 것을 말한다.

자바에서는 동적 바인딩을 통해 오버라이딩된 메소드가 항상 실행되도록 보장한다.

라. 오버라이딩과 super 키워드

  • Q: 그렇다면 슈퍼클래스의 메소드는 이제 더 이상 쓸모없게 된 것일까?
    A: super 키워드를 통해 정적바인딩으로 슈퍼클래스의 멤버에 접근할 수 있다.

  • 오버로딩과 오버라이딩
    오버라이딩 : 슈퍼 클래스에 있는 메소드와 이름, 매개변수, 타입의 개수, 리턴 타입 등이 모두 동일한 메소드가 서브 클래스에 재정의 되었을 경우

오버로딩 : 한 클래스나 상속 관계에 있는 클래스에 서로 다른 매개 변수의 타입이나 개수가 다른 여러 개의 메소드가 같은 이름으로 작성되는 것

7) 추상 클래스

상속에서 추상 클래스는 중요한 슈퍼 클래스의 역할을 함

가. 추상 메소드

abstract 키워드와 함께 원형만 선언되고, 코드는 작성되지 않은 메소드이다.

abstract public String getName();
abstract public String fail() { return "Good Bye";}

나. 추상 클래스 선언

추상클래스 : abstract로 선언한 클래스

1> 추상 메소드를 최소 한 개 이상 가지고 abstract로 선언된 클래스

abstract class Shape{
	
    abstract pulbic void draw();
}

2> 추상 메소드가 없이도 abstract로 선언한 클래스

abstract class JComponent{
	public void load(String name){
    	this.name = name;
    }
}

추상 메소드를 가지고 있으면 반드시 추상 클래스로 선언되어야한다.
추상 클래스의 인스턴스를 생성할 수 없다.(추상 클래스에는 실행 코드가 없는 미완성 상태인 추상 메소드가 있을 수 있기 때문)

다. 추상 클래스의 상속과 구현

1> 추상 클래스의 상속

추상 메소드를 가진 추상 클래스를 상속받는 서브 클래스는 자동으로 추상 클래스가 된다.(추상 메소드를 상속 받기 때문)

2> 추상 클래스의 구현

서브 클래스에서 슈퍼 클래스의 모든 추상 메소드를 오버라이딩하여 실행 가능한 코드로 구현하는 것(인스턴스 생성 가능)

라. 추상 클래스의 목적(나 진짜 이거는 서브 클래스에서 구현 다시 해야겠다!)

인스턴스를 생성하기 위함이 아니라 상속을 위한 슈퍼 클래스로 활용하기 위한 것임
-> 서브 클래스가 구현할 메소드의 원형을 알려주는 인터페이스!

8. 인터페이스

인터페이스 : 하드웨어 장치들이 상호 데이터를 주고받을 수 있는 규격을 의미함

  • Q: 이런규격이 왜 필요할까?
    A: 컴퓨터 메인 보드를 만드는 회사와 주변 장치를 만드는 회사 사이에는 약속이 필요하기 때문임.
    메인보드와 주변 장치 사이의 기계적 전기적 접속 규격과 데이터 전송 규격을 정해놓고 이것을 지킨다면 메인보드를 누가 만들건 문제없이 결합 될 수 있다.

자바에서도 협업시 인터페이스를 작성해놓고 이를 구현하여 오버라이딩하는 방법이 서로 맞추기 좋다. (추상된 틀을 만든다)

1) 자바 인터페이스

키워드를 사용하여 클래스를 선언하듯이 선언함 [public | default]

public interface PhoneInterface{
	public static final int TIMEOUT = 10000;
    public abstract void sendCall();
    public abstract void receiveCall();
    public default void printLogo(){
    	Systemn.out.println("** Phone **"),
    }
}

인터페이스는 다음 5종류의 멤버로 구성됨
필드(멤버 변수)를 만들 수 없다.
1) public 상수 필드
2) public 추상메소드
3) public default 메소드
4) public static 메소드
5) private 메소드
6) private static 메소드

  • 자바 8 이후로는 인터페이스에서 default 메서드나 static 메서드를 선언할 수 있게 되었으나, 이러한 경우를 제외하고는 인터페이스의 모든 메서드는 추상 메서드로 간주된다.

인터페이스의 객체는 생성할 수 없음

2) 인터페이스 상속

인터페이스는 다른 인터페이스를 상속할 수 있다.
상속을 통래 기존 인터페이스에 새로운 규격을 추가한 새로운 인터페이스를 만든다.
상속 시 extends 키워드를 이용한다.

interface MobilePhoneInterface extends PhoneInterface {
	void sendSMS(); 
    void receiveSMS(); 
}
  • 인터페이스는 2개 이상의 인터페이스를 다중 상속도 가능하다.
interface MusicPhoneInterface extends PhoneInterface, Mp3Interface {
...
}

3) 인터페이스 구현

implements 키워드를 사용하여 인터페이스를 모든 추상 메소드를 구현한 클래스를 작성하는 것

인터페이스에 선언된 추상 메서드는 구현 클래스에서 반드시 오버라이딩되어야 한다.

class SamsungPhone implements PhoneInterface{
	@Override
	public void sendCall(){
    	System.out.println("띠리리리링");
        }
        
    @Override
    public void receiveCall() {
    	System.out.println("전화가 왔습니다.");
        }
        
    public void flash() {
    	System.out.println("전화기에 불이 켜졌습니다.");
    }
       
}

4) 클래스 상속과 인터페이스 구현

클래스를 상속하면서 동시에 인터페이스를 구현할 수 있다.

0개의 댓글