상속(Inheritance)
상속이란, 기존에 있던 클래스를 재사용하여 새로운 클래스를 생성하는 것이다.
즉 상속을 받는 클래스는 상속하는 클래스의 멤버변수와 메소드를 상속받는다.
상속하는 클래스 : 상위 클래스, 부모 클래스, base class, super class
상속받는 클래스 : 하위클래스, 자식 클래스, derived class, sub class
기존에 있던 클래스보다 더 구체적인 기능을 가진 클래스를 구현해야할 때 기존 클래스를 상속을 하게된다.
자식 클래스는 부모 클래스의 멤버들을 상속 받게 되어 자식클래스는 부모 클래스를 포함하는 형태가 된다.
상속은 아래와 같이 extends(확장)를 사용해 작성한다.
class Child extends Parent{
}
extends 뒤에는 단 하나의 클래스만 올 수 있다.
c++에서는 다중상속을 지원하지만 자바의 상속은 단일 상속(single inheritance)만을 지원하기 떄문이다.
상속을 사용하는 이유
상속을 하면 하위클래스가 상위클래스에서 더 구체적인 개념과 기능을 가지게 되어 확장에 용이하다.
그러한 이유때문에 코드의 재사용성이 높아져 코드의 추가 및 수정이 쉬워진다.
생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.
자손 클래스의 멤버개수는 조상클래스보다 항상 같거나 많다.
super 키워드
super 키워드는 상속관계에서 상위 클래스에 대한 참조 값을 가리킨다.
super()를 호출하게 되면 상위 클래스의 기본 생성자를 호출한다.
this와 비슷한 개념으로 사용이 되며 아래 예제와 같이 이름이 같은 변수가 있을 때 구분을 할 수 있게 된다.
class Parent{
int age = 40;
}
public class Child extends Parent{
int age = 20;
void printAge(){
System.out.println(age); // 20
System.out.println(this.age); // 20
System.out.println(super.age); // 40
}
public static void main(String[] args) {
Child child = new Child();
child.printAge();
}
}
상속 관계 생성과정
자식 클래스의 인스턴스를 생성하게 되면 우선 부모 클래스의 기본생성자를 호출한다.
그 후 자식 클래스의 생성자를 호출하는 방식으로 객체가 생성됨을 볼 수 있다.
class Parent{
Parent() {
System.out.println("Parent 생성자");
}
}
class Child extends Parent{
Child() {
System.out.println("Child 생성자");
}
}
class Main{
public static void main(String[] args) {
Child child = new Child();
// "Parent 생성자"
// "Child 생성자"
}
}
포함관계
코드를 재사용하는 방법에는 상속 말고도 포함(Composite)관계가 있다.
클래스 간 포함관계를 맺어주는 것은 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 뜻한다.
예시를 보면 Circle 클래스의 멤버변수로 Point가 들어감으로서 포함관계가 이루어 진다.
class Circle{
int radius;
Point p = new Point();
}
class Point{
int x;
int y;
}
IS-A vs HAS-A
상속관계와 포함관계 중 어떤 방식으로 클래스와 관계를 맺어줄 지 어렵다면 이 두가지를 적용하면 쉽게 알 수 있다.
IS-A (상속 관계)
- "~은 ~이다"가 성립되는 관계 ex) A SportsCar is a Car.
- 일반적인 개념과 그것을 상속 받아 구체적인 개념으로 생성하는 방식
- 상속은 결합도가 높은 설계 방식이다.
HAS-A(포함 관계)
- "~은 ~을 가지고 있다"가 성립되는 관계 ex) A Circle has a Point.
- 클래스가 다른 클래스를 멤버변수로 포함한다.
오버라이딩(overriding)
오버라이딩이란 상위 클래스에서 선언되어 있는 메소드를 상속 받아 변경하는 것이다.
상속받은 메서드를 하위 클래스에 맞게 변경해야 하는 경우 오버라이딩하여 사용한다.
class Circle extends Shape{
@Override
void printInfo(){
System.out.println("Circle class");
}
}
class Shape{
void printInfo(){
System.out.println("Shape class");
}
}
오버라이딩의 조건
- 이름이 같아야 한다.
- 매개변수가 같이야 한다.
- 리턴 타입이 같이야 한다.
그러나 접근제어자와 예외는 제한된 조건 하에 다르게 변경 할 수 있다.
어노테이션
2번 라인에 있는 @Override와 같은 @가 붙은 문구를 어노테이션이라고 한다.
주석과도 같이 취급되며 컴파일러에게 이 함수는 오버라이드 된 함수라고 알려주는 기능을 하며 컴파일러는 해당 함수가 상위 클래스에 존재하는 지 확인하여 에러 여부를 표시한다.
가상함수(virtual function / virtual method)
오버라이딩을 하게 되면 같은 이름의 메소드가 상위 클래스와 하위 클래스에 총 두 개가 존재하게 된다.
컴파일러는 포인터 타입의 메소드를 호출하기 때문에 다형성을 이용할 때 문제가 생긴다.
즉 아래의 c++ 코드를 보면 person 포인터 변수가 가지고 있는 주소의 타입은 Developer이지만 peroson의 함수가 호출 되는 것을 알 수 있다.
class Person{
public:
void speak(){
cout << "I'm a person" << endl
}
};
class Developer:public Person{
public:
void speak(){
cout << "I'm a Developer" << endl
}
};
int main(){
Person *person;
Developer developer;
person = &developer;
person->speak(); //"I'm a person"
}
그렇다면 다형성을 적용할때에는 어떻게 오버라이드 된 함수를 호출 할 수 있을까?
c++에서는 virtual 이라는 키워드를 함수에 사용하면 해당 함수는 가상함수가 되어 가상함수 테이블이 생긴다.
자바는 모든 메소드가 가상메소드이기 때문에 다형성을 사용해 하위 클래스로 객체를 생성했다면 재정의된 메소드가 실행된다.
가상함수 테이블은 클래스마다 존재하며 메서드의 이름과 주소 값을 가리키고 있어 오버라이드 된 메소드는 부모 클래스의 메소드와 다른 주소값을 저장하고 있는 것을 알 수 있다.
가상 함수 테이블에 주소 값이 저장되어 있기 때문에 다형성을 구현하여 오버라이딩을 했을 때 자동으로 생성된 객체의 메소드가 호출이 된다.
class Person{
void speak(){
System.out.println("I'm a Person");
}
void eat(){
System.out.println("냠냠");
}
}
class Developer extends Person{
@Override
void speak(){
System.out.println("I'm a Developer");
}
void coding(){
System.out.println("coding,,,");
}
}
class Main{
public static void main(String[] args) {
Person person = new Person();
Developer developer = new Developer();
Person perdev = new Developer();
person.speak();
developer.speak();
perdev.speak();
// I'm a Person
// I'm a Developer
// I'm a Developer
}
}
'Language & Framework > Java' 카테고리의 다른 글
[JAVA] :: 자바 기초 6 :: 인터페이스 (Interface) (0) | 2021.07.25 |
---|---|
[JAVA] :: 자바 기초 5 :: 다형성 / InstanceOf / Abstract Class / Upcasting & Downcasting (0) | 2021.07.22 |
[JAVA] :: 자바 기초 3 :: Static / Singleton Patton / Array / ArrayList (0) | 2021.07.10 |
[JAVA] :: 자바 기초 2 :: 생성자 / 오버로딩 / 접근제어자 / 정보은닉 (0) | 2021.07.06 |
[JAVA] :: 자바 기초 1 :: 객체 / 클래스 / 인스턴스 / 속성 / 함수 / 메소드 (2) | 2021.07.04 |