본문 바로가기

[책]명품 JAVA Programming

명품 자바 프로그래밍 5장 요약

상속의 개념

객체 지향에서 상속은 부모 클래스에 만들어진 필드와 메소드를 자식 클래스가 물려받는 것이다. 상속은 클래스들 간의 상속이므로 객체 사이의 상속이 아니다. 자식 클래스로 만든 자식 객체는 자식 클래스의 모든 멤버는 물론 부모 클래스의 모든 멤버를 같이 가직 생성된다. 상속은 코드 중복을 제거하여 클래스를 간결하게 구현할 수 있게 합니다. 애초에 상속 자체가 편의성을 위해 나온건데 당연한거죠! 

 

자바의 상속 선언

extends를 클래스명 뒤에 붙이면 됩니다. 그러면 그냥 클래스였던 것이 extends전이 자식클래스가 되고 후가 부모클래스가 됩니다.

자식클래스명 extends 부모클래스명

 

교재에서 자식 클래스를 서브 클래스로 부르고 부모 클래스를 슈퍼 클래스로 종종 바꿔서 부르는데 둘다 같은 말 입니다..! 헷갈리게 해놨네요.

서브 클래스 객체 생성도 특별한건 없고 여태 했던대로 객체 생성 하시면 됩니다. 단지 클래스 생성할때 extends를 추가했을 뿐입니다.

 

서브 클래스는 슈퍼 클래스 멤버를 모두 생성하고 사용한다고 했죠? 그럼 슈퍼 클래스 멤버에 접근해야 할겁니다. 이때 슈퍼 클래스 내의 멤버의 접근지정자를 잘 살펴봐야 합니다. 접근 지정자가 private로 돼있으면 접근하지 못하는 멤버고 나머지는 접근 할수 있죠. 대체로 변수들을 private로 설정해두고 특정 함수로 이들에 접근하도록 합니다.

예를들어 private int x; 로 설정해 두고 아래 함수로 public void setX(int x){this.x = x;}로 여기에 접근하도록 합니다. 많이 봤죠 이런거.

 

자바 상속의 특징

상속 특1) 다중 상속 못함. 부모 클래스로 딱 한개만 가질 수 있음.

상속 특2) 하나의 부모 클래스가 여러 자식 클래스에게 상속을 줄 수는 있음.

상속 특3) Object라는 클래스가 항상 계층의 최상위로 상속 받아져 있음. 유일하게 Object클래스만 상속 안받는 클래스.

Object클래스는 다음장에서 배웁니다!

 

여담이지만 하나의 .java 파일에서 public이 붙은 클래스는 하나만 만들어 집니다. 이미 앞선 예제 풀면서 public class로 선언했다가 오류 나서 public을 지운 경험이 있을수도 있겠네요. public 클래스는 .java의 파일명과 동일한 이름이여야만 생성 됩니다. 가독성의 이유로 그런 제한을 걸어 두었다고 하네요! 기본적으로 class는 public의 속성을 가지니 사용하는데에 참고하시면 좋겠습니다.(혹시 틀렸다면 댓글 부탁드려요.). (- -)(_ _)

 

서브와 슈퍼클래스 생성자 호출

부모 클래스부터 생성합니다. 부모 클래스가 부모 클래스를 가진다면 그것 먼저 호출 합니다. 그다음 자식 클래스가 호출 되고 최종적으로 본인이 호출한 클래스가 호출 되는 겁니다. 부모 클래스의 모든 멤버를 사용하기 위해 호출과정이 필요 합니다.

 

super()

클래스를 만들때 클래스 객체를 생성할때 사용하는 생성자를 내부에 코딩 해 놓습니다. 그리고 자식 클래스가 호출되기전 부모 클래스가 먼저 호출되어 생성 되는데 그때 생성자는 뭐가 될까요? 여태까지의 책의 예시들은 컴파일러가 자동으로 기본 생성자로 슈퍼 클래스를 호출한 것입니다. 하지만 서브 클래스에서 슈퍼 클래스를 호출할 때 명시적으로 어떤 생성자로 생성할지 정하도록 하는게 국룰 입니다. 그때 쓰이는것이 바로 super() 입니다.

서브 클래스의 생성자가 슈퍼 클래스의 생성자를 부를때 super(생성자 요소 넣을 자리) 요소 자리에 멤버를 넣어 어떤 생성자로 생성할지 맨 철줄에 작성 해야 합니다.

 

업캐스팅

서브 클래스로 만든 객체를 슈퍼 클래스의 객체로 취급할 수 있습니다. 왜냐하면 서브 클래스로 만든 객체에는 슈퍼 클래스의 멤버 모두가 자동으로 생성되기 때문입니다.

캐스팅 이란? 타입을 변경하는 것으로 형변환 이라고도 합니다.

서브 클래스의 객체에 대한 레퍼런스를 슈퍼 클래스 타입으로 변환하는 것을 업캐스팅 이라고 합니다. 슈퍼 클래스로 레퍼런스 변수를 만들어 놓고 서브 클래스로 만들어놓은 객체를 가리키는겁니다.

업캐스팅한 경우 슈퍼 클래스의 멤버만 접근 가능하다. 서브 클래스 객체를 가리키더라도 서브 클래스 고유의 멤버는 접근할 수 없다.

업캐스팅을 왜 쓸까요? 업캐스팅한 경우 슈퍼 클래스의 멤버만 접근 가능하다. 이것 때문에 쓰겠구나 라는건 알겠는데 아직 확 와닿진 않죠. 동일한 슈퍼 클래스를 상속받은 여러 서브 클래스가 있을때 이를 판단하는 과정을 스킵하고 바로 서브 클래스를 확정할 수 있을때 사용하면 편리합니다.

 

업캐스팅의 반대말인 다운캐스팅도 있습니다. 자식 클래스 레퍼런스가 부모 클래스 객체를 가리키는건데 이건 명시적으로 형변환을 해줘야 합니다.

 

instance of로 업캐스팅, 다운캐스팅한 레퍼런스가 원래 어떤 클래스인지 알 수 있습니다.

 

메소드 오버라이딩

슈퍼클래스에서 정의해놓은 함수 재작성하기 입니다. 내용을 전부 바꿔도 좋고 참고해 추가해도 좋습니다. 파일 덮어쓰기 정도로 이해하셔도 될것 같습니다. 대부분 오버라이딩 할 메소드들은 슈퍼클래스 에서는 아무것도 작성해 놓지 않고 자식 클래스에서 사용하도록 합니다.

오버라이딩 할때 개인적으로 반드시 지켜야 하는 규칙이라고 생각되는게 @Override 입니다. 이는 자식 클래스가 부모 클래스의 함수를 오버라이딩 한다는 뜻인데, 이를 작성하지 않아도 아무 오류도 뜨지 않습니다. 하지만 본인은 오버라이딩 했다 라고 생각하고 send 함수를 작성했는데 sned 라고 함수명을 잘못 작성했을때 새로운 함수가 만들어진 겁니다. 이때 @Override 를 위에 쓴다면 함수명이 달라진걸 오류로 보여줍니다! 그러므로 오버라이딩 할때 잊지말고 @Override 하세요.

자바는 동적바인딩 방식으로 오버라이딩된 메소드를 실행 한다.

    동적바인딩(Dynamic Binding)

   - 다형성 메소드 출력방식.

   - Runtime에 함수 성격이 결정된다.

   - 메소드의 매개변수에 따라 실행되는 함수가 결정된다.

 

    정적바인딩(Dynamic Binding)

   - 기본적인 메소드 출력방식.

   - 컴파일에 함수와 변수 성격이 결정된다.

 

 

285p 예제를 보면 Shape b = new Circle(); 코드는 업캐스팅이죠? 따라서 Shape에 있는 draw() 함수가 호출 되는게 아니라 Circle에 있는 draw() 함수가 호출 됩니다. 만약 여기에 Rectangle 클래스가 Shape 클래스를 상속 받았다고 가정 해봅시다. 그 후 Shape b 가 업캐스팅 하지 않고 draw()함수가 호출 되었다면 Rectangle인지 Circle인지 판단하는 코드를 draw()에 작성해야 합니다! 이걸 업캐스팅을 사용한 예시로 볼 수 있죠.

 

추상 클래스와 추상 메소드

추상 메소드(abstract method)는 코드는 없는 함수명만 있는 메소드 입니다. 자식 클래스가 자유롭게 오버라이딩 하도록 혹은 반드시 이 함수명으로만 오버라이딩 하도록 제약을 하기 위함입니다.

추상 클래스(abstract class)는 추상 메소드를 가지고 있는 클래스 입니다. 추상 메소드가 있으면 반드시 추상 클래스로 선언해야 합니다.  추상 메소드를 가지고 있지 않지만 추상 클래스로 선언할 수도 있습니다. 왜 추상 클래스를 만들까요?

추상 클래스는 객체를 생성할 수 없습니다. 왜냐하면 객체 생성을 목적으로 만드는 클래스가 아니라 상속해서 사용하기 위해 만들기 때문입니다. 따라서 본인이 코드를 작성할때 반드시 상속으로만 접근하도록 클래스를 구현하고 싶다면 사용하는것이 abstract class 입니다. 상속 받을때 또한 abstract를 붙여 추상 클래스임을 명시해야 합니다.

추상 클래스에 선언된 모든 추상 메소드는 반드시 구현해야 합니다. 

 

인터페이스

클래스와 유사하지만 조금 다른 것이 인터페이스 입니다. 인터페이스는 프로그램 코드를 짜기전 일종의 틀을 만들어 놓는것입니다.

 

인터페이스 특1) 객체를 생성할 수 없음, but 레퍼런스 변수는 선언 가능함.

인터페이스 특2) 인터페이스끼리 상속 가능함.

인터페이스 특3) 추상 클래스처럼 상속받으면 모든 추상 메소드를 구현해야함.

인터페이스 특4) 여러개 구현 가능함.

 

인터페이스 구현시 클래스 상속의 extends 가 아닌 implements 로 인터페이스를 구현하도록 클래스를 짤 수 있습니다. 이때 인터페이스 내에 있는 추상 메소드를 작성하면 됩니다. 상속(extends)는 인터페이스들 끼리만 가능하고 클래스가 인터페이스를 구현하는건 implements입니다!