좋은 개발자가 되기위한 방법들/객체지향

객체지향 4대특성 (상속) 쉽게정리

chief_sac 2021. 10. 12.
반응형

 

객체지향 프로그래밍에서의 4대특성이라 하는 것중 정리하는 마지막것은 상속입니다. 상속이란 앞에서 다뤘던 특성들중 프로그래밍에서만 듣게되는 다른 특성들과는 다르게 미디어, 일상들속에서 듣기쉬운 단어입니다. 우리가 일상에서 사용하는 상속은 " 뒤를 잇는 일" 이라는 의미를 가지고있습니다. 이는 프로그래밍에서도 크게 다르지 않는데

참고자료

  • 오브젝트: 코드로이해하는 객체지향설계 (저자: 조영호),
  • 객체지향의 사실과 오해 (저자: 조영호)
  • TCPSchool.com( Java Part.43 다형성의개념)

 

상속이란?


 

기존의 클래스에 기능을 추가하거나 다시정의하여서 새로운 클래스를 만드는것을 의미합니다. 이는 다형성에서 포함다형성과 연관이 됩니다.
  • 상속을 이요하면 기존에 정의되어있는 클래스의 모든 필드와 메소드를 물려받아, 새로운 클래스를 상속 할 수 있습니다.

  • 이때 기존에 정의된 클래스를 부모(parent class) 또는 상위(super class), 기초(base class)라고 지칭합니다.

  • 또한 새롭게 작성되는 클래스는 자식(child class), 하위(sub class), 파생(derived class)라고 부릅니다.

 

책에서 나온 필자의 주장에

"상속의 진정한 목적은 코드재사용성이아니라 다형성을 위한 서브타입 계층을 구축하는것이다"

 

라 말하고있다. 물론 포함다형성(서브타입 다형성 )의 경우 서브타입을 생성할 때에 상속만을 사용하는 것은 아니지만 일차적인 목적은 코드 재사용성보다는 서브타입의 구현을 의미하는 바가 더 크다.

그럼에도 어째서 상속을 사용하는가?

 

다형성과 상속

 

  • 포함다형성에서 상속을 사용하는 가장 큰 이유로는 상속은 클래스들을 계층으로 쌓아서 상황에따라 적절한 메서드를 사용 할 수있는 매커니즘을 제공한다.

 

  • 위에 적은 말이 말하는 바는 객체가 어떠한 메세지를 수신하였을때 객체지향 시스템에서는 메세지를 적절하게 처리할 행동을 탐색하는데 그것을 상속계층의 구성이 어떻게 되어있는지를 보며 따라가며 처리한다는 것이다.

 

다형성을 설명하는 것 보다는 상속에대한 이야기를 정리하고싶어 다형성에 관한것은 정리하여 게시글로 올려놨기 때문에 다시 상속을 기준으로 돌아오겠습니다.

 

 

상속의 장점

 

 

자바에서 클래스의 상속은 아래와 같은 장점을 가지고있는데

  • 기존에 작성된 클래스를 다시 사용가능합니다.
  • 하위 클래스를 설계할 때 중복되는 멤버를 부모에 작성해 놓는다면 불필요한 중복을 줄일 수 있습니다.
  • 클래스간의 계층 관계를 구성하여 다형성의 기초개념에 힘을 실어줄 수 있습니다.

그렇다면 상속은 코드 재사용성을 위해서만 사용하는가? 또 그것은 아니라고 합니다. 상속을 타입계층에 대한 고민없이 사용한다면 이해가 어려울 뿐 아니라 유지보수에 난감한 코드를 작성하게 될 확률이 높아 진다고합니다.

이러한 문제를 해결하기위해서는 상속을 이해하기위해 필요한 개념을 여러가지로 이해하고 설계해야하는데

  • 업캐스팅
    • 자바에서 sub 클래스는 super클래스의 모든 특성을 상속받는데 sub 클래스는 super클래스로 취급될 수 있다. 이부분에서 업케스팅은 서브클래스의 객체가 수퍼 클래스 타입으로 형변환 되는것을 말한다.
    • 과학에서 가장 많이 등장하는 동물로 코드를 작성하여 살펴 본다면
      public class CastingEX(
      	public static void main(String[] args) {
      		Pets pets = new Pets("cat");		
      		Animal animal = pets;
      		animal.kind = "cat";  // 여기는 가능하지만
      		animal.name = "나비"; // 컴파일에러뜸
      	}
      )
      
      class Animal {
      	String kind;
      
      	public Animal(String kind) {
      		this.kind = kind;
      	}
      }
      
      class Pets extends Animal{
      	String name;
      
      	public Pets(String kind){
      		super(kind);
      	}
      }​
    이렇게 작성된 코드에서는 자신의 클래스에 속한 멤버만 접근이 가능하고 name의 경우 Pets타입의 멤버여서 컴파일 오류가 뜹니다. 이렇게 업캐스팅을 하면 객체내에 있는 모든 멤버에 접근 할 수 없고 수퍼 클래스의 멤버에게만 접근이 가능합니다.

 

  • 동적 메서드탐색
    • 동적메서드를 탐색한다는 것은 단순한데 메세지를 수신한 객체는 먼저 생성한 자신의 클래스에 적합한 메서드가 있는지를 검사하고 부모클래스에서 메서드를 탐색하는데 이것이 상속되어있는 계층을 전부 뒤지면서 만약 존재하면 실행 존재하지않으면 예외를 발생시키며 종료된다.

 

  • 동적 바인딩
    • 어떠한 메세지를 수신하였을때 실행되는 메서드가 런타임에서 결정이되는데 구체클래스가 아닌 추상 클래스에 의존하여 정의된 퍼블릭 인터페이스에 메세지를 전송하게되면 구체클래스 중에서 업캐스팅 되어있는 구체클래스의 메서드가 처리한다.
    • 즉 동적 바인딩이란 실행될 메스드를 런타임에 결정하는 방식을 말한다.

 

  • self 참조
    • 동적 메서드와의 연관이 높은 self참조는 변수인데 객체가 메세지를 수신하면 컴파일러는 self 참조라는 임시변수를 스스로 생성하고 메세지를 수신한 객체를 가르키도록 사용된다.
    • 동적메서드 탐색에서는 self가 가르키는 객체에서 시작하여 상속계층의 역방향으로 탐색하고 탐색이 종료되면 self참조는 소멸한다.(자바에서는 self보다는 this로 사용된다.)

 

  • super참조
    • self와는 대비되는 변수로 자식클래스에서 부모클래스의 인스턴스 변수나 메서드에 접근하기 위해서 사용된다.
    • super참조의 용도는 명확하게 부모클래스에 정의된 메서드를 사용하기위한 것이라는것 보다는 해당 클래스의 부모클래스에서부터 메서드를 탐색하라는 느낌이다.

위와 같은 개념을 통해 상속을 조금더 이해하면된다.

상속의 개념에대해서는 오버라이딩과 오버로딩을 이야기 듣기도하는데 이 부분에대해서 알고있다면 위 내용이 이해가 빨랐을것 같았는데 순서를 조금 잘못 공부하며 정리한 것 같다.

 

오버로딩과 오버라이딩

 

오버로딩(overloading)이란 서로 다른 시그니처를 갖는 여러 메소드를 하나의 이름으로 정리하는 것을 뜻한다.
  • 처음 자바를 공부할때 뭐가다른지 정말 이해하기 힘들었던 부분인데 쉽게말해 오버로딩은 새로운 메서드를 정의하는것, 오버라이딩은 있는(상속받은) 기존 메서드를 다시 정의하는것으로 받아들이면 편하다.

 

오버라이딩,메소드 오버라이딩

 

오버라이딩이란 상속관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 메소드로 재정의 하는것을 말합니다.
  • 이 개념은 자바를 통해서 자주 접하였기 때문에 어느정도 이해가 가능했다.

 

  • 대신 오버라이딩은 조건이있는데 부모의 메서드보다 접근제한자를 작게 변경할 수 없고, 큰 범위의 예외를 선언 할 수 없습니다.

메소드 오버라이딩은 상속받은 부모의 메서드를 자식이 재정의 할 수 있음을 말하는데 코드 예시가 이해가 빨리되었다.

class Parent {

    void display() { System.out.println("부모 클래스의 display() 메소드입니다."); }

}

class Child extends Parent {

    void display() { System.out.println("자식 클래스의 display() 메소드입니다."); }

}

 

public class Inheritance05 {

    public static void main(String[] args) {

        Parent pa = new Parent();

        pa.display();

        Child ch = new Child();

        ch.display();

        Parent pc = new Child();

        pc.display(); // Child cp = new Parent();
				/* 결과
					부모 클래스의 display() 메소드입니다.
					자식 클래스의 display() 메소드입니다.
					자식 클래스의 display() 메소드입니다.
				*/
    }

위와 같이 객체지향에서 말하는 4대특성 마지막 상속을 정리하면서 마무리를 지었다. 결국 이또한 내가 누군가에게 설명 할 수 없다면 내가가 알고있는 것이 아닌것이다. 적어놓는다고 내 것이 되는게 아님을 알기에 지속적으로 다시보며 한번씩 잘못적은것을 수정하며 성장해야 할것같다.

반응형

댓글0