Java 상속

I C-AN·2021년 7월 24일
0

Java

목록 보기
11/26
post-thumbnail

상속 (Inheritance)

  • 상속(inheritance)이란 기존의 클래스에 기능을 추가하거나 재정의하여 새로운 클래스를 정의하는 것을 의미
  • 상속을 이용하면 기존에 정의되어 있는 클래스의 모든 필드와 메소드를 물려받아, 새로운 클래스를 생성할 수 있다 (생성자, 초기화블럭 제외)
class Parent { }
class Child extends Parent { }

상속의 특징

  1. 기존에 작성된 클래스를 재활용할 수 있다
  2. 자식 클래스 설계 시 중복되는 멤버를 미리 부모 클래스에 작성해 놓으면, 자식 클래스에서는 해당 멤버를 작성하지 않아도 된다
  3. 클래스 간의 계층적 관계를 구성함으로써 다형성의 문법적 토대를 마련할 수 있다
  4. 자손 클래스의 변경은 조상 클래스에 영향을 미치지 않는다

Object 클래스

자바 클래스의 최상위 클래스로 모든 자바의 클래스는 Object 클래스를 상속받는다
때문에 extends 키워드로 상속을 명시하지 않아도 Object 클래스의 모든 멤버를 자유롭게 사용할 수 있다

포함 관계

class Point {
	int x;
	int y;
}

// Point 클래스와 관계 없음
class Circle1 {
	int x;
	int y;
	int r;
}

// Point 클래스와 포함 관계
class Circle2 {
	Point c = new Point(); // 참조변수 선언
	int r;
}

Circle1 c1 = new Circle(); // x, y, r 멤버 생성
Circle2 c2 = new Circle(); // r과 참조변수 c 멤버 생성

클래스의 멤버로 참조변수를 선언하는 것
작은 단위의 클래스를 만들고, 이 들을 조합해서 클래스를 만든다

클래스 간의 관계를 판단하는 쉬운 방법

상속관계 "~은 ~이다" (is-a)
포함관계 "~은 ~을 가지고 있다" (has-a)

원은 점이다 - Circle is a Point
원은 점을 가지고 있다 - Circle has a Point

단일 상속

class Tv { 
	boolean power;
	int channel;

	void power() { power = !power; }
	void channelUp() { ++channel; }
	void channelDown() { --channel; }
}

class DVD {
	boolean power;

	void power() { power = !power; }
	void play() {}
	void stop() {}
	void rew() {}
	void ff() {}
}

class TvDVD extends Tv, DVD { } // 에러, 조상은 하나만 허용

class TvDVD extends Tv{
	// 포함관계 객체 사용
	DVD dvd=new DVD(); 
	
	void play() { dvd.play(); }
}

Java는 단일 상속만을 허용한다 (하나의 부모만 상속)
비중이 높은 클래스 하나만 상속관계로 나머지는 포함관계로 한다

오버라이딩 (Overriding)

상속받은 조상의 메서드를 재정의하여 사용하는 것

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

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

public class prac {
	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();
	}

}

오버라이딩의 조건

  1. 선언부가 조상 클래스의 메서드와 일치해야 한다
  2. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다
  3. 예외를 조상 클래스의 메서드보다 많이 선언할 수 없다

오버로딩 vs 오버라이딩

class Parent {
	void parentMethod() {}
}

class Child extends Parent {
	void parentMethod() {} // 오버라이딩
	void parentMethod(int i) {} // 오버로딩

	void childMethod() {} // 메서드 정의
	void childMethod() {} // 중복 정의
	void childMethod(int i) {} // 오버로딩
}

오버로딩 : 기존에 없는 새로운 메서드를 정의하는 것
오버라이딩 : 상속받은 메서드의 내용을 변경하는 것

참조변수 super

객체 자신을 가리키는 참조변수
인스턴스 메서드, 생성자 내에서만 존재 (static 메서드에서 사용불가)
조상의 멤버를 자신의 멤버와 구별할 때 사용

class Parent { int a = 10; }
 
class Child extends Parent {
	int a = 20;
    void display() {
        System.out.println(a); // 20
        System.out.println(this.a); // 20 자신의 멤버 a
        System.out.println(super.a); // 10 조상의 멤버 a
    }
}

public class Prac {
    public static void main(String[] args) {
        Child ch = new Child();
        ch.display();
    }
}

생성자 super()

조상의 생성자를 호출할 때 사용
조상의 멤버는 조상의 생성자를 호출해서 초기화
반드시 모든 생성자의 첫 줄에 다른 생성자를 호출해야 한다
호출하지 않으면 컴파일러가 생성자의 첫 줄에 super()를 삽입하면서 컴파일러 에러가 생길 수 있다

class Parent {
	int a;

	Parent() { a = 10; }
	Parent(int n) { a = n; }
}

class Child extends Parent {
	int b;
    
	super(40); // 조상 생성자 호출
	Child() { b = 20; }

	void display() {
		System.out.println(a); // 40
		System.out.println(b); // 20
	}
}

public class prac {
	public static void main(String[] args) {
		Child ch = new Child();
		ch.display();
	}
}
profile
할 수 있다

0개의 댓글