Java inheritance(상속)
1. inheritance(상속)이란?
하나의 클래스가 다른 클래스의 특징을 상속받은 채로 설치되는 것
종의 분류와 비슷하다고 볼 수 있다.
2. Inheritance(상속)의 장점
2-1. 모듈화
하나의 클래스를 잘 설치해두면 그 클래스를 기반으로 다른 클래스를 생성할 수 있다.
만약 수정 사항이 생기면 최상위 부모 클래스만 수정하면 그에 따른 수정 결과가 자식 클래스에게 상속됨
2-2. 재사용성
겹치는 attribute나 method가 있을 때 번거롭게 코드를 두 번 쓰지 않아도 된다.
3. Inheritance(상속) 사용 문법
extends를 이용해서 상속을 수행할 수 있다.
class Point{
int x, y;
public void move(int dx, int dy){x += dx; y += dy;}
}
class Point3d extends Point{
int z;
public void move(int dx, int dy, int dz)
{x += dx; y += dy; z += dz;}
}
4. "Is-a" rule of inheritance
B 가 is a A의 관계일 때만 상속을 시켜줄 수 있다.
ex) Programmer is a person.
Mama also is a person.
Programmer와 Mama 클래스 모두 Person 클래스에서 상속 받을 수 있다.
그러나 "has-a" 관계일 때는 상속 불가능
ex) CarOwner has a Car
CarOwner는 Car 클래스에게 상속을 받을 수 없다.
5. 상속 관계
상속을 해주는 클래스를 부모 클래스(Superclass)
상속을 받는 클래스를 자식 클래스(Subclass)
라고 한다.
모든 클래스는 Object class의 자식 클래스!
5-1. Object class
모든 클래스는 default(extends를 사용하지 않아도)로 Object에 상속된다.
Object class의 대표적인 method들
(1) toString()
: object를 String으로 선언할 때의 값을 반환(ex) System.out.println(Object))
(2) getClass()
: class object를 반환할 때 class 대표형을 나타낸다.
(3) equals()
: class 간의 equality를 반환하는 method
finalize(), clone(), hashCode(),,....
해당 method들을 overriding을 통해서 자식 class에서 사용할 수 있다!
5-2. 상속의 종류
(1) Single Inheritance
(2) Multi-level Inheritance
(3) Hierarchical Inheritance
(4) Multiple Inheritance
: 여러 super class에게 상속을 받는 형태이지만,
java에서는 해당 상속을 허용하지 않는다.
단 여러 interface에 대해서는 상속이 가능하다.
6. Overriding & Hiding
6-1. Overriding
subclass는 override를 통해 superclass의 method를 재정의해서 사용할 수 있다.
(단, constructor는 overriding 불가능)
overriding을 하기 위한 조건
1. C가 A의 subclass여야 하고,
2. override하고자 한 method는 같은 func name, argument types, order(signature)를 가지고 있어야 한다.
3. 해당 method는 protected or public이다.
@Override notation을 쓰면 compiler가 미리 해당 method가 super class에 선언되어 있는지 확인하기 때문에 typo error를 방지할 수 있다.
class Parent{
void printName() {System.out.println("Parent");}
}
class Child extends Parent {
@Override /* it raise an error if there is no "printName" method in "Parent" class
*/
void printName() {System.out.println("Child");}
}
6-2. Hiding
static method는 overriding이 아닌 hiding을 사용하는데, upcasting을 할 때 선언된 type으로 static method를 불러오게 된다.
static method의 경우 hiding이 사용된다.
inor.tistory.com/7 에서 들고 온 hiding의 예시
class Car{
public void accelate(){
System.out.println("일반 엔진 사용");
}
public static void stop(){
System.out.println("일반 브레이크 사용");
}
}
class RacingCar extends Car{
@Override
public void accelate(){
System.out.println("레이싱카 전용 엔진 사용");
}
public static void stop(){
System.out.println("레이싱카 전용 브레이크 사용");
}
}
public class Overriding {
public static void main(String[] args) {
Car myCar = new RacingCar();
//일반 메서드
myCar.accelate();
// "레이싱카 전용 엔진 사용" 출력
//클래스 메서드
myCar.stop();
// "일반 브레이크 사용" 출력
}
}
출처: https://inor.tistory.com/7 [Inor]
6-3. Type Casting
하나의 데이터 타입을 다른 데이터 타입으로 바꾸는 것.
casting은 instance 그 자체의 타입(actual type)을 바꾸지 않고, explicit data type만 바꾸게 된다.
Upcast : superclass의 타입으로 casting 하는 것
Downcast : subclass의 타입으로 casting하는 것
Upcasting은 별다른 요구사항 없이 intrinsic으로 자동으로 이루어진다.
Parent parent1 = new Child(); // Intrinsic Casting
Parent parent2 = (Parent) (new Child()); // Explicit Casting
class Parent{
void printName() {System.out.println("Parent");}
}
class Child extends Parent {
@Override
void printName() {System.out.println("Child");}
}
Child child = new Child();
child.printName(); //Child
Parent parent = (Parent) child;
parent.printName(); //Child
/* parent still points to the instance of the Child class Casting does NOT change
the type of the instance itself. */
Downcasting
: explicit하게 cast를 해줘야 함.
runtime 때 type checking이 이루어짐
class Parent{
void printName() {System.out.println("Parent");}
}
class Sister extends Parent {
@Override
void printName() {System.out.println("Sister");}
}
class Brother extends Parent {
@Override
void printName() {System.out.println("Brother");}
}
Parent parent = (Parent) (new Sister());
parent.printName(); //Sister
Brother sister = (Brother) parent;
/* Exception in thread "main"
java.lang.ClassCastException: class Sister cannot be cast to class Brother
*/
6-4. super
keyword
super
를 사용해서 subclass 내부에서 superclass로 접근할 수 있다.
class T1 {String s() {return "1";}}
class T2 extends T1 {String s() {return "2";}}
class T3 extends T2 {String s() {return "3";}
void test(){
System.out.println("s() = " + s());
System.out.println("super.s() = " + super.s());
System.out.println("((T2)this).s() = " + ((T2)this).s());
System.out.println("((T1)this).s() = " + ((T1)this).s());
}
}
T3 t3 = new T3();
t3.test();
/*
s() = 3
super.s() = 2
((T2)this).s() = 3
((T1)this).s() = 3
*/
super();
를 사용해서 superclass의 constructor를 선언할 수도 있다.
하지만 direct하게 grandparent에 접근하는 것은 금지되어 있음
ex) super.super();
또한 subclass constructor에 superclass constructor를 선언하지 않아도 default로 superclass를 선언하게 된다.
class Point {
int x, y;
Point() {x = 1; y = 1;}
}
class ColoredPoint extends Point {
int color = 0xFF00FF;
}
//main method
ColoredPoint cp = new ColoredPoint();
System.out.println(cp.color);
//Order of execution
ColoredPoint() {super();}
Point() {super();}
Object() {}
x = 1; y = 1;
int color = 0xFF00FF;;
7. 접근 제한자
7-1. Public & protected
subclass에게 상속되며 overriding이 가능하다.
7-2. Default vs Protected
default는 package 밖에 있는 subclass에 상속이 안되지만
protected는 가능
package 사이의 interaction을 관리할 때 둘을 구분한다.
7-3. Private
private한 member들은 상속은 되지만 subclass에서 접근할 수 없음.
getter나 setter를 이용한 indirect way로 접근 가능
7-4. Final
final class는 상속되지 않는다.
method를 final로 선언하면 해당 method가 overriding되는 것을 방지할 수 있다.
variable을 final로 선언하면 해당 variable은 갱신되지 않는다.