상속(Inheritance)
- 기존의 클래스로 새로운 클래스를 작성하는 것.(코드의 재사용)
class 자식클래스 extends 부모클래스{
// ...
}
- 두 클래스를 부모와 자식으로 관계를 맺어주는 것.
class Parent { } //부모클래스
class Child extends Parent{
// Child 클래스에 Parent 클래스를 상속받는다.
// ...
}
- Child 클래스와 Parent 클래스는 상속관계에 있다고 이야기한다.
- 자손은 조상(부모의부모)의 모든 멤버를 상속받는다.(생성자, 초기화블럭 제외)
- 자손의 멤버 개수는 조상보다 적을 수 없다.(같거나 많다.)
class Parent{ int age; } class Child extends Parent{ // 자신의 멤버 0개 // 상속받은 멤버 1개 } |
- 자손의 변경은 조상에 영향을 미치지 않는다.
- 반대로 조상의 변경은 자손에게 영향을 준다.
왜? 상속 받고 있으니깐 ~
class Parent { int age; } class Child extends Parent{ void play(){ syso("놀자~"); } } |
참고.
변수와 메서드의 모음을 멤버라고 한다.
확장 -> extend
class Point { int x; int y; } class Point3D extends Point { int z; } |
Point3D p = new Point3D(); |
상속 |
객체 생성 |
- 두 코드의 결과는 같다.
실습 예제.
package com.seulgae.ch07;
class Tv {
boolean power; // 전원상태(on/off)
int channel; // 채널
void power() { power = !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class CaptionTv extends Tv { // SmartTv는 Tv에 캡션(자막)을 보여주는 기능을 한다.
boolean caption; // 캡션상태(on/off)
void displayCaption(String text) {
if (caption) { // 캡션 상태가 on(true)일 때만 text를 보여 준다.
System.out.println(text);
}
}
}
class CaptionTvTest {
public static void main(String args[]) {
CaptionTv ctv = new CaptionTv();
// channel cannot be resolved or is not a field, 채널이라는걸 해석 못하겠음 !
ctv.channel = 10; // 조상 클래스로부터 상속받은 멤버
ctv.channelUp(); // 조상클래스로부터 상속받은 멤버
System.out.println(ctv.channel);
ctv.displayCaption("Hello, World");
ctv.caption = true; //캡션(자막)기능을 켠다.
ctv.displayCaption("Hello, World");
}
}
포함 관계
▶ 포함(composite) 이란?
- 클래스의 멤버 변수로 참조변수를 선언하는 것.
class Circle{
int x; // 원점의 x좌표
int y; // 원점의 y좌표
int r; // 반지름(radius)
}
- 작은 단위의 클래스를 만들고, 이 들을 조합해서 클래스를 만든다.
class Circle{
Point c = new Point(); // 원점
int r; // 반지름(radius)
}
class Car {
Engine e = new Engine(); // 엔진
Door[] d = new Door[4]; // 문, 문의 개수를 넷으로 가정하고 배열로 처리했다.
}
클래스 간의 관계 결정하기
상속관계(10%) | '~은 ~이다.(is-a)' |
포함관계(90%) | '~은 ~을 가지고 있다.(has-a)' |
- 상속, 포함 관계를 결정할 때 문장으로 만들어보고 뭐가 더 자연스러운지 판단하면 된다.
- 근데 대부분 포함관계를 사용한다.
실습 예제.
package com.seulgae.ch07;
class MyPoint{
int x;
int y;
}
//class Circle2 extends MyPoint { // 상속
// int r;
//}
class Circle2 { // 포함
MyPoint p = new MyPoint(); // 참조변수의 초기화
int r;
}
public class InheritanceTest {
public static void main(String[] args) {
Circle2 c = new Circle2();
c.p.x = 1;
c.p.y = 2;
c.r = 3;
System.out.println("c.p.x= " + c.p.x);
System.out.println("c.p.y= " + c.p.y);
System.out.println("c.r= " + c.r);
}
}
단일 상속(Single Inheritance)
- Java는 단일상속만을 허용한다.(C++은 다중상속 허용)
- 다중 상속은 충돌 위험이 많아 자바는 다중 상속 대신 인터페이스를 사용하여 다중 상속 문제를 해결한다.
단일상속이란?
class TvDVD extends Tv, DVD{ // 에러. 조상은 하나만 허용된다.
//다중 상속 안됨!
}
- 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 한다.
Object클래스 - 모든 클래스의 조상
- 부모가 없는 클래스는 자동적으로 Object 클래스를 상속받게 된다.
- 모든 클래스는 Object 클래스에 정의된 11개의 메서드를 상속받는다.
- toString(), equals(Object obj), hashCode(), ... (9장에서 배울꺼임)
실습 예제.
- 참조변수가 들어오면 toString()을 호출함.
package com.seulgae.ch07;
class MyPoint{
int x;
int y;
}
class Circle2 extends Object{ // 포함
MyPoint p = new MyPoint(); // 참조변수의 초기화
int r;
// Circle2(){ // 참조변수의 초기화
// c = new MyPoint();
// }
}
public class InheritanceTest {
public static void main(String[] args) {
Circle2 p = new Circle2();
System.out.println(p.toString()); //Circle2@4926097b 문자열 반환
Circle2 c2 = new Circle2();
System.out.println(c2); //Circle2@39ed3c8d 문자열 반환
}
}
오버라이딩(overriding) - 덮어쓰다.
- 상속받은 조상의 메서드를 자신에 맞게 변경하는 것
실습 예제.
package com.seulgae.ch07;
class MyPoint3 extends Object{
int x;
int y;
//생성자 : 인스턴스 초기화 메서드
MyPoint3(int x, int y){
this.x = x;
// this가 붙으면 매개변수에 x가아닌 바로 위 인스턴스 메서드를 가르킨다.
// 변수이름이 같아서 혼동하지 말자.
this.y = y;
}
// Object 클래스의 toString()을 오버라이딩
public String toString() {
return "x:"+x+", y:" +y;
}
}
public class OverrideTest {
public static void main(String[] args) {
MyPoint3 p = new MyPoint3(3, 5);
System.out.println(p);
}
}
오버라이딩(overriding) 조건 3가지
1. 선언부가 조상 클래스의 메서드와 일치해야 한다.
+ 선언부(반환타입, 메서드이름, 매개변수 목록)
2. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
- public, protected, (default), provate
3. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
오버로딩과 오버라이딩 차이점.
오버로딩(overloading) | 기존에 없는 이름이 같은 새로운 메서드를 정의하는 것(new) 상속하고 관계x |
오버라이딩(overriding) | 상속받은 메서드의 내용을 변경하는 것(change, modify) 상속하고 관계o |
참조변수 super = this(lv와 iv 구별하는데 사용했었음.)
- 객체 자신을 가리키는 참조변수. 인스턴스 메서드(생성자)내에만 존재(static 메서드 내에서 사용불가)
- 조상의 멤버를 자신의 멤버와 구별할 때 사용
실습 예제.
package com.seulgae.ch07;
class SuperTest {
public static void main(String args[]) {
Child2 c = new Child2();
c.method();
}
}
class Parent2 {
int x=10; /* super.x */
}
class Child2 extends Parent2 {
int x = 20; //this.x
void method() {
System.out.println("x=" + x);
System.out.println("this.x=" + this.x);
System.out.println("super.x="+ super.x);
}
}
package com.seulgae.ch07;
class SuperTest2 {
public static void main(String args[]) {
Child2 c = new Child2();
c.method();
}
}
class Parent2 { /* super.x와 this.x 둘 다 가능 */
int x=10;
}
class Child2 extends Parent2 {
int x=20;
void method() {
System.out.println("x=" + x);
System.out.println("this.x=" + this.x);
System.out.println("super.x="+ super.x);
}
}
super() - 조상의 생성자
- 조상의 생성자 호출할 때 사용
- 조상의 멤버는 조상의 생성자를 호출해서 초기화
class Point {
int x, y;
Point(int x, int y){
this.x = x; // iv 초기화
this.y = y;
}
}
class Point3D extends Point{
int z;
Point3D(int x, int y, int z) {
this.x = x; //조상의 멤버를 초기화
this.y = y; // 조상의 멤버를 초기화
this.z = z;
}
}
Point3D(int x, int y, int z) {
super(x, y); // 조상클래스의 생성자Point(int x, int y)를 호출
this.z = z; // 자신의 멤버를 초기화
}
- 조상의 생성자를 호출해서 조상의 생성자가 조상의 멤버를 초기화 한다.
(추가조건) 생성자의 첫 줄에 반드시 생성자를 호출해야 한다.
그렇지 않으면 컴파일러가 생성자의 첫 줄에 super();를 삽입
'Study > Java' 카테고리의 다른 글
객체지향 프로그래밍 7장(30강 ~ 35강) (0) | 2022.06.07 |
---|---|
객체지향 프로그래밍 7장(25강 ~ 29강) (0) | 2022.06.06 |
객체지향 프로그래밍 6장(16강 ~ 19강) (0) | 2022.06.03 |
객체지향 프로그래밍 6장(11강 ~ 15강) (0) | 2022.06.03 |
객체지향 프로그래밍 6장(6강 ~ 10강) (0) | 2022.06.02 |