포스트

22. 중첩 클래스와 상속

인터페이스와 추상 클래스에 대해 알아가보자.

22. 중첩 클래스와 상속

상속

상수를 이용하지 않는 기능 추가의 문제점

  1. 기존 코드에 기능 추가
    1. 변경하기 전에 이 클래스를 사용해서 만든 프로젝트에 영향을 줄 수 있다.
    2. 기존 코드를 손 댔을 때 오류 발생 위험이 있다.
    3. 프로젝트를 수행할 때 마다 고객의 요구사항을 맞추기 위해 코드를 덧붙이다보면 누더기가 될 수 있다.
  2. 기존 코드를 복사해서 기능 추가
    1. 장점 : 기존 코드를 손대지 않는다. ⇒ 기존코드를 사용한 프로젝트에 영향을 주지 않음
    2. 단점 : 중복코드가 발생됨
      1. 기능 추가 : 복사 코드에도 기능 추가해야함 ⇒ 유지보수가 어려움
      2. 기존 코드 버그 수정 : 복사코드도 버그 수정해야함 ⇒ 유지보수가 어려움

상속을 이용할 때

기존 코드를 손대지 않고 기능 추가

1
2
3
class Car2 extends Car{ - }
// Car2 : 새 클래스(= 자식 클래스, sub class)
// Car  : 기존 클래스(= 부모 클래스, super class)
  • 장점 : 기존 코드를 손대지않는다 ⇒ 기존 코드를 사용한 프로젝트에 영향을 주지 않는다.

상속은 기존 코드를 자동으로 복사해오는 것이 아니다. 기존 코드를 제 것처럼 사용할 수 있는 권한을 획득하는 것이다.

상속과 인스턴스 생성

인스턴스 생성

1
2
new Score2();
// [ name | kor | eng | math | sum | aver | music | art ]
  • 서브 클래스의 인스턴스를 만들 때 수퍼 클래스의 인스턴스 필드로 생성한다.

상속과 메서드 호출

1
2
3
4
5
6
7
8
class A{ void m1(){ - } }
class B extends A{ void m2(){ - } }
class C extends B{ void m3(){ - } }
class D extends C{ void m4(){ - } }

B obj = new B(); // obj > 200[ A | B ]
obj.m2();
obj.m1(); // super class의 코드를 제 것처럼 사용할 수 있다.

상속과 클래스 로딩

상속 UML

상속 클래스 로딩

상속과 생성자, super();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Object{ - }
class A extends Object{
	int v1;
	// public A(){ super(); }
}
class B extends A{
	int v2;
	// public B(){ super(); }
}
class C extends B{
	int v3;
	// public C(){ super(); }
}

	C obj = new C();
	// 사용자가 따로 생성자를 지정하지 않고 호출할 경우 자바가 자동으로 생성자를 만드는데 이때 부모 클래스의 생성자를 호출하는 super()를 컴파일러가 자동 삽입한다.

super( )

모든 생성자는 첫 문장으로 슈퍼 클래스의 생성자를 호출하는 코드를 갖고 있다.
개발자가 명시적으로 작성하지 않으면 슈퍼클래스의 default constructor를 호출하는 코드를 자동 삽입한다. ← 컴파일러가 삽입함

1
2
3
4
5
6
7
8
9
10
11
class A {
	int v1;
	public A(int a){ super(); }
}
class B{
	int v2;
	public B(){ 
		super();    // 불가
		super(100); // 가능
	}
}

상속 분류

  1. Specialization
    • 좀 더 특별한 클래스를 정의할 때 사용하는 상속 Specialization
  2. Generalization
    • 서브 클래스들의 공통 분모를 추출 Generalization

추상 클래스

  • 서브 클래스에 공통 필드나 메서드를 상속해주는 역할 추상클래스
1
new Car(); // 추상 클래스는 인스턴스 생성이 불가하다. 

추상 메서드

  • 정의하고 해당 기능을 구비하게 만드는 규칙자 추상메서드

추상 메서드와 호출

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Car{
	String model, maker, capacity;
	abstract void run();
}
class Sedan extends Car{
	String sunroof;
	run(){ - }
	doSunroof(){ - }
}

Car obj = new Sedan(); // 200[ model | maker | capacity | sunroof | ... ]
obj.run();             // 컴파일러 : 레퍼런스의 타입에서 메서드가 있는지 찾음     -> Car class에서 run()을 찾는다
											 // JVM   : 레퍼런스가 실제 가리키는 객체의 클래스에서 찾음 -> Sedan에서 run()을 찾는다.
											 
obj.doSunroof();       // Car class에서 doSunroof가 없어 컴파일러에서 에러가 남

다중 상속이 없는 이유

다중 상속

1
2
3
4
5
C obj = new C();

// 어떤 변수에 넘겨야할지 결정할 수 없다.
obj.v2 = 3.14;
obj.v2 = 100;

왼쪽처럼 다중 상속된 C에서 위 코드처럼 값을 넘길 때 A에 넘겨야 할지 B에 넘겨야 할지 판단 불가하다.
그래서 자바는 다중 상속을 지원하지않는다.

다형적 변수

여러 타입의 객체를 참조하는 레퍼런스

1
2
3
4
5
6
7
8
9
10
11
12
13
class X{ - }
class A extends X{ - }
class B extends X{ - }
class C extends B{ - }

X obj; // 다형적 변수 : 슈퍼 클래스인 X로 선언했기 때문에 A, B, C를 모두 받을 수 있는 변수이다.
obj = new X();
obj = new A();
obj = new B();
obj = new C();

obj.인스턴스 변수    // X의 서브 클래스는 무조건 X의 인스턴스 변수를 갖는다. (= 자식 클래스의 인스턴스는 부모 클래스의 인스턴스 변수를 갖는다.)
obj.인스턴스 메서드   // X의 인스턴스 변수를 사용하는 인스턴스 메서드

레퍼런스와 인스턴스 변수

1
2
3
4
5
6
7
8
9
10
11
12
class X{ - }
class A extends X{ - }
class B extends X{ - }
class C extends B{ - }

B obj;         // 이 레퍼런스를 이용하여 B, X의 인스턴스 변수를 사용 할 수 있어야한다.
obj = new X(); // 생성된 객체 [ X ]         -> 불가
obj = new A(); // 생성된 객체 [ X | A ]     -> 불가
obj = new B(); // 생성된 객체 [ X | B ]     -> 가능
obj = new C(); // 생성된 객체 [ X | B | C ] -> 가능

C obj = new C();

결론. 레퍼런스는 자식 클래스의 인스턴스 주소를 저장해도 된다. → 변수에 여러 타입의 객체 주소 저장 가능 = 다형적 변수

다형적 변수 - 상속관계

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Vehicle{
	String model, capacity;
}
class Bike extends Vehicle{
	String engine;
}
class Car extends Vehicle{
	String cc, value;
}
class Sedan extends Car{
	String sunroof, auto;
}
class Truck extends Car{
	String ton, zip;
}

Bike b = new Bike(); // 200[ modle | capacity | engine ];  [ vehicle 변수 | Bike 변수 ]
b.Vehicle 멤버(필드, 메서드) // 가능
b.Bike 멤버               // 가능

Vehicle v = b;           // 200
v.Vehicle 멤버            // 가능
v.Bike 멤버               // 컴파일 오류

this와 super 키워드와 필드 접근

this, super 필드

this와 super 키워드와 메서드 접근

this, super 메서드

다형적 변수와 메서드 호출

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class A{
	m(){ - };
}
class A2 extends A{
	m(){ - };
	x(){ - };
}
class A3{
	y(){ - };
}

A obj = new A();
obj.m();         // A.m()
((A2)boj).x();   // 컴파일 OK | 실행 NO > 예외발생

A2 obj2 = new A2();
obj2.m();        // A2.m()
obj2.x();        // A2.x()

A obj3 = new A3();
obj3.m();        // A2.m()
obj3.y();        // 컴파일 오류
((A3)obj3).y();  // 컴파일 OKc A3.y()
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.