[INA470] Java Programming Youn-Hee Han http://link.kut.ac.kr 11. 상속 [INA470] Java Programming Youn-Hee Han http://link.kut.ac.kr
1. 상속의 개요 상속(Inheritance)의 장점 상속을 통하여 기존 클래스의 필드와 메소드를 재사용 기존 클래스의 일부 변경도 가능 상속을 이용하게 되면 복잡한 GUI 프로그램을 손쉽게 작성 상속은 이미 작성된 검증된 소프트웨어를 재사용 신뢰성 있는 소프트웨어를 손쉽게 개발, 유지 보수 코드의 중복을 줄일 수 있다.
1. 상속의 개요 상속 슈퍼 클래스 (Superclass) 서브 클래스 (Subclass) 상속 예 이미 존재하는 클래스 상속을 받는 클래스 상속 예 예를 들어, 일반적인 Car 클래스가 이미 구현되어 있다면 새로 만들려는 SportsCar를 위한 클래스를 새로 작성하는 것보다 Car 클래스를 상속받으면서 SportsCar 클래스를 작성하는 것이 쉽다. class Car { int speed; } class SportsCar extends Car { int turbo; 상속한다는 의미
1. 상속의 개요 서브 클래스와 슈퍼 클래스간의 관계 상속이 되는 것의 실체 서브 클래스는 슈퍼 클래스를 포함한다. 서브 클래스는 슈퍼 클래스가 가지고 있는 모든 멤버들을 상속받으면서 자신이 필요한 멤버를 추가함. 상속이 되는 것의 실체 슈퍼 클래스의 public 과 protected로 선언된 모든 필드와 모든 메소드 package 멤버는 슈퍼 클래스와 서브 클래스가 같은 패키지에 있을 때 상속된다.
1. 상속의 개요 서브 클래스와 슈퍼 클래스의 예 상속의 강점 슈퍼 클래스로부터 상속된 필드와 메소드들을 교체 및 상세화시킬 수 있으며 자신이 새로운 필드와 메소드들을 추가할 수도 있다.
1. 상속의 개요 상속 계층 구조 (Inheritance Hierarchy) 상속 관계는 일반적으로 트리 모양 의 계층 구조를 형성한다. 옆 상속 계층도에 맞춘 클래스 정의 클래스들의 크기 비교 슈퍼 클래스는 서브 클래스들의 공통 부분이 된다.
1. 상속의 개요 상속은 중복을 줄인다. 예를 들어 Car, Truck, Bus는 모두 가속 페달을 밟아서 가속시키고 브레이크 페달을 밞아서 감속시킨다. 이들 각각을 모든 클래스 안에 구현할 경우의 그림 공통적인 부분 및 특징을 지닌 새로운 클래스 Vehicle을 먼저 만들고 이 Vehicle을 상속받아 Car, Truck, Bus 를 구현한 그림
1. 상속의 개요 Car is a Vehicle 상속의 is-a 관계 has-a 관계 “서브 클래스” is a “슈퍼 클래스” 예 자동차는 탈것이다., 사자는 동물이다., 개는 동물이다., 고양이는 동물이다. has-a 관계 has-a 관계가 성립하면 이 관계는 상속 모델을 사용하면 안된다. 이 경우는 포함하는 클래스의 필드로서 포함되는 클래스 및 타입등을 선언하면 된다. 도서관은 책을 가지고 있다. (Library has a book) 거실은 소파를 가지고 있다. 선은 두 개의 점을 가지고 있다. Car is a Vehicle class Point { int x; int y; } class Line { Point p1; Point p2;
2. 상속 사용 Car와 SportsCar 예제 public class Car { public int speed; // 속도 Car.java public class Car { public int speed; // 속도 public int gear; // 주행거리 public String color; // 색상 public void setGear(int newGear) { gear = newGear; } public void speedUp(int increment) { speed += increment; public void speedDown(int decrement) { speed -= decrement; class SportsCar extends Car { boolean turbo; public void setTurbo(boolean newValue) { turbo = newValue; }
2. 상속 사용 Car와 SportsCar 예제 (계속) public class CarTest { CarTest.java public class CarTest { public static void main(String[] args) { SportsCar c = new SportsCar(); c.color = “Red”; c.setGear(3); c.speedUp(100); c.speedDown(30); c.setTurbo(true); } 슈퍼 클래스에서 public 으로 선언되어 있으면 서브 클래스에서도 public이 된다.
3. 메소드의 재정의 오버라이딩 (Overriding, 재정의) Animal과 Dog 클래스에서 오버라이딩 예 서브 클래스가 필요에 따라 상속된 메소드를 다시 정의하는 것 상속받은 메소드들을 자기 자신의 필요에 맞추어서 변경하는 것 Animal과 Dog 클래스에서 오버라이딩 예
3. 메소드의 재정의 오버라이딩의 조건 B 메소드는 A 메소드의 이름, 반환형, 매개 변수의 개수 및 데이터 타입과 정확하게 일치하여야 한다. A 메소드는 public이나 protected로 선언되어 있어야 한다. private으로 선언된 A 메소드는 오버라이딩할 수 없다. B 메소드의 접근 지정자는 A 메소드의 접근 지정자보다 더 좁은 범위로 지정할 수 없다. 슈퍼 클래스에 정의된 A 메소드 서브 클래스에서 오바라이딩하는 B 메소드
3. 메소드의 재정의 오버라이딩과 관련된 실수 오버라이드가 아님 public class Animal { public void makeSound() { … } }; 이와 같은 경우 컴파일러는 아무런 에러를 발생시키지 않는다. 오버라이드가 아님 public class Dog extends Animal { public int makeSound() { … } }; Annotation인 @Override는 컴파일러에게 지금 정의하는 메소드 는 오버라이드하는 메소드임을 알려주게 된다. 그래서, 오버라이드 조건이 맞지 않으면 컴파일 에러가 발생한다. public class Dog extends Animal { @Override public int makeSound() { … } };
3. 메소드의 재정의 오버라이딩과 오버로딩의 차이 Overloading Overriding 같은 이름의 메소드를 시그너쳐만 틀리게 하여 여러 개 정의하는 것 Overriding 슈퍼 클래스에 정의된 메소드를 서브 클래스에서 다시 정의하는 것
3. 메소드의 재정의 필드 재정의 서브 클래스에서 슈퍼 클래스에서 정의한 필드와 동일한 필드를 정의하면 서브 클래스의 필드가 슈퍼 클래스의 필드를 덮어버리게 (오버라이드) 된다. super 서브 클래스에서 오버라이드한 슈퍼 클래스의 필드 및 메소드를 참조하거나 호출하는 방법 Static 인 경우 슈퍼 클래스의 이름.메소드명(…) 슈퍼 클래스의 이름.필드명 Instance 변수인 경우 super.메소드명(…) super.필드명 this는 현재 객체를 참조하기 위하여사용되는 반면, super는 슈퍼 클래스의 메소드나 필드를 참조하기 위하여 사용
3. 메소드의 재정의 메소드 및 필드 재정의 예제 수퍼클래스 객체를 가리킨다.
3. 메소드의 재정의 메소드 호출 순서 오른쪽과 같은 상속 계층 구조에서 Eagle 객체를 생성하여 다음과 같이 메소드를 호출 하였을 때 어떤 메소드 가 호출되는가? Eagle e = new Eagle(); e.sleep() // Animal의 sleep() 호출 e.eat() // Eagle의 eat() 호출 e.sound() // Bird의 sound() 호출
4. 접근 지정자 상속받는 것의 실체와 접근 지정자 Override 시의 규칙 슈퍼 클래스의 public 과 protected로 선언된 모든 필드와 모든 메소드 package 멤버는 슈퍼 클래스와 서브 클래스가 같은 패키지에 있을 때 상속된다. private 멤버는 상속되지 않는다. Override 시의 규칙 서브 클래스에 오버라이드 할 시에 접근을 더 제한하는 접근 지정자를 사용할 수 없다. 예 슈퍼 클래스에서 protected로 선언된 메소드는 서브 클래스에서 재정의시 public 으로 선언은 가능하지만 private으로는 선언할 수 없다. 인스턴스 메소드를 정적 메소드로 변경할 수 없다.
4. 접근 지정자 접근 지정자 예제
4. 접근 지정자 접근 지정자 예제
5. 상속과 생성자 super(…)를 활용한 명시적인 호출 서브 클래스 생성자에서 슈퍼 클래스 생성자 호출
5. 상속과 생성자 묵시적인 호출 1 서브 클래스의 객체가 생성될 때 슈퍼 클래스의 디폴트 생성자가 자동으로 호출된다.
5. 상속과 생성자 묵시적인 호출 2 슈퍼 클래스에 디폴트 생성자가 정의되어 있지 않아도 기본적으로는 디폴트 생성자가 숨어 있으므로 그것을 호출한다.
5. 상속과 생성자 묵시적인 호출 3 슈퍼 클래스에 다른 생성자가 정의되면 디폴트 생성자가 없어지기 때문에 이런 경우에는 super(…) 없이 서브 클래스에서 슈퍼 클래스의 디폴트 생성자 호출이 불가 public Shape(String msg) { System.out.println(“Shape 생성자()” + msg); } 컴파일 오류 발생! : 디폴트 생성자를 호출할 수 없음
6. Object 클래스 Object 클래스 클래스를 정의할 때 extends 키워드와 함께 명시적으로 슈퍼 클래스를 선언하지 않아도 자동으로 Object 클래스를 상속하게 됨 즉, 자바의 모든 클래스는 Object 클래스의 서브클래스이다. 자바 클래스 계층 구조의 최상위 클래스이다.
6. Object 클래스 Object 클래스에 정의된 메소드 위 메소드들은 매우 Generic 하다. 즉, 구체적인 정의가 되어 있지 못하다. 그래서, 대부분의 경우 서브 클래스에서 Object 클래스에 정의된 메소드 중 일부를 오버라이드를 통하여 구체적으로 정의를 하게 된다.
6. Object 클래스 clone() 메소드 equals() 메소드 현재의 클래스와 슈퍼 클래스가 Cloneable 인터페이스를 구현하고 있다면 그 클래스의 객체에 대해 다음과 같이 복사본을 생성할 수 있다. 현재 클래스와 슈퍼 클래스에 대해 clone() 메소드의 행동양식은 사용자가 직접 재정의해야 한다. Object 클래스의 행동양식은 Object 클래스에 정의되어 있다. equals() 메소드 == 연산자는 객체의 실체 (Object ID)가 같은지를 비교하지만 equals() 메소드는 객체를 설계하는 사람 입장에서 “같다”의 내용을 스스로 재정의하여 사용할 수 있는 메소드 obj.clone();
6. Object 클래스 equals() 메소드 예제 모델명이 같으면 같은 자동차라는 판단을 하는 equals() 메소드 정의 Car.java public class Car { … // 기존 필드들 private String model; // model 필드 추가 public Car(String model) { // 생성자 추가 this.model = model; } public String getModel() { // getter 추가 return model; public boolean equals(Object obj) { // equals() 메소드 정의 if (obj instanceof Car) return model.equals(((Car) obj).getModel()); else return false;
6. Object 클래스 equals() 메소드 예제 (계속) public class CarTest { CarTest.java public class CarTest { public static void main(String[] args) { Car firstCar = new Car("HMW520"); Car secondCar = new Car("HMW520"); if (firstCar.equals(secondCar)) { System.out.println("동일한 종류의 자동차입니다."); } else { System.out.println("동일한 종류의 자동차가 아닙니다."); }
6. Object 클래스 finalize() 메소드 hashCode() 메소드 getClass() 메소드 객체가 소멸되기 직전에 Garbage Collector에 의하여 호출되는 콜백 (callback) 메소드 Object 클래스에서는 아무것도 하지 않지만 서브 클래스에서 재정의하여 자원을 반납하는 등의 정리 과정을 수행할 수 있다. hashCode() 메소드 객체의 ID 값의 역할을 할 수 있는 객체 고유의 값을 돌려준다. getClass() 메소드 해당 객체의 클래스 (Class) 타입의 객체를 돌려준다.
6. Object 클래스 toString() 메소드 Object 클래스에서는 다음과 같은 내용을 반환하도록 정의됨 서브 클래스에서 재정의하여 서브 클래스 객체의 내용이 잘 표현될 수 있도록 한다. getClass().getName() + '@' + Integer.toHexString(hashCode()) Car.java public class Car { … // 기존 필드들 … // 기존 생성자들 … // 기존 메소드들 public String toString() { // toString 메소드 추가 return “모델: ” + model; } Car firstCar = new Car(“HMW520”); System.out.println(firstCar.toString()); System.out.println(firstCar);
7. 종단 클래스와 메소드 final (종단) 클래스 final (종단) 메소드 상속을 시킬 수 없는 클래스 (보안상의 이유) 대표적인 예: String final 클래스의 내무 멤버 필드와 메소드들은 오버라이드될 수 없다. final (종단) 메소드 final 클래스가 아닌 일반 클래스에서 특정 메소드를 서브 클래스에서 오버라이드할 수 없도록 만든 메소드 final class String { … }