TIL-23-03-06
Updated:
상속
상속의 정의
- 기존의 클래스를 재사용해서 새로운 클래스를 작성하는 것.
- 두 클래스를 조상과 자손으로 관계를 맺어주는 것.
- 자손은 조상의 모든 멤버를 상속받는다.(생성자, 초기화블럭 제외)
- 자손의 멤버갯수는 조상보다 적을 수 없다. (같거나 많다.)
- 보다 적은 양의 새로운 클래스를 작성할 수 있고, 코드의 추가 및 변경이 용이하다.
class Point {
int x;
int y;
}
class Point3D extends Point{
int z; // Point3D 클래스는 자동적으로 int x, int y가 추가된 것과 같은 효과를 얻으므로
// int z만 정의해주면 된다.
}
클래스간의 관계 - 상속관계
- 공통부분은 조상에서 관리하고 개별부분은 자손에서 관리한다.
- 조상의 변경은 자손에 영향을 미치지만, 자손의 변경은 조상에 아무런 양향을 미치지 않는다.
- 같은 코드를 하나 이상의 클래스에 중복적으로 추가해야하는 경우, 상속관계를 이용하여 코드의 중복을 최소화해야 한다. (변경 부분 누락으로 인한 오작동 방지)
클래스간의 관계 - 포함관계
- 클래스의 멤버로 참조변수를 선언하는 것
- 작은 단위의 클래스를 먼저 만들고, 이들을 조합해서 하나의 커다란 클래스를 만든다.
- 코드가 간결해지고, 관리도 수월한 장점이 있다.
class Point {
int x;
int y;
}
class Circle {
int x; // 원점의 x좌표
int y; // 원점의 y좌표
int r; // 반지름(radius)
}
↓
class Circle {
Point c = new Point(); // 원점
int r
}
클래스간의 관계 결정하기
- 문장을 만들어보면 클래스 간의 관계가 보다 명확해진다.
원(Circle)은 점(Point)이다 -> Circle is a Point. (상속관계)
원(Circle)은 점(Point)을 가지고 있다. -> Circle has a Point. (포함관계) - 원은 원점과 반지름으로 구성되므로 두번째 문장이 더 옳다. 따라서 Circle 클래스와 Point 클래스는 포함관계를 맺어주는 것이 옳다.
- 보통의 경우 90% 이상은 포함관계이므로, 관계가 애매할 때는 일단 포함관계로 작성해도 괜찮다.
- 프로그램의 모든 클래스를 분석하여 가능한 많은 관계를 맺드록 노력해서 코드의 재사용성을 높여야 한다.
class Shape { // 도형을 의미하는 클래스
String color = "black";
void draw() {
System.out.printf("[color=%s]%n", color);
}
}
class Point {
int x;
int y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
Point() {
this(0,0);
}
String getXY() {
return "("+x+","+y+")"; //x와 y의 값을 문자열로 반환
}
}
class Circle extends Shape {
Point center; // 원의 원점좌표
int r; // 반지름
Circle() { // Circle(Point center, int r을 호출
this(new Point(0,0),100);
}
public Circle(Point center, int r) {
this.center = center;
this.r = r;
}
void draw() { // 원을 그리는 대신에 원의 정보를 출력하도록 했다.
System.out.printf("[center=(%d, %d), r=%d, color=%s]%n",
center.x, center.y, r, color);
}
}
class Triangle extends Shape {
Point[] p = new Point[3]; // 3개의 Point인스턴스를 담을 배열을 생성한다.
Triangle(Point[] p) {
this.p = p;
}
void draw() {
System.out.printf("[p1=%s, p2=%s, p3=%s, color=%s]%n",
p[0].getXY(), p[1].getXY(), p[1].getXY(), color);
}
}
public class DrawShape {
public static void main(String[] args) {
Point[] p = {new Point(100, 100), new Point(140, 50), new Point(200,100)};
Triangle t = new Triangle(p);
Circle c = new Circle(new Point(150,150), 50);
t.draw(); // 삼각형을 그린다.
c.draw(); // 원을 그린다.
}
}
단일상속
- 자바는 단일상속만을 허용한다.
- 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 한다.
class Tv {
boolean power;
int channel;
void power() { power = !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class VCR {
boolean power;
int counter = 0;
void power() { power = !power; }
void play() { /*...*/}
void stop() {/*...*/}
void rew() {/*...*/}
void ff() {/*...*/}
}
class TVCR extends Tv {
VCR vcr = new VCR(); // VCR클래스를 포함시켜서 사용한다.
void play() {
vcr.play();
}
void stop() {
vcr.stop();
}
void rew() {
vcr.rew();
}
void ff() {
vcr.ff();
}
}
Object 클래스 - 모든 클래스의 조상
- 조상이 없는 클래스는 자동적으로 Object 클래스를 상속받게 된다.
- 상속계층도의 최상위에는 Object 클래스가 위치한다.
- 모든 클래스는 Object클래스에 정의된 11개의 메서드를 상속받는다.
- toString(), equals(Object obj), hashCode(), …