상속

#상속 #메소드 오버라이딩 #다형성 #구성(Composition)
Dec 22, 2023
상속
  • 기존에 존재하는 클래스로부터 필드와 메소드를 상속
  • 자바 상속 특징 - 다른 상속 지원 X
    • 다른 상속 - 여러 개의 클래스로부터 상속받는 것
Circle 메소드 실행 → 부모 Shape 우선 호출 → circle 실행
Circle 메소드 실행 → 부모 Shape 우선 호출 → circle 실행
class Shape{ int x, y; public Shape(){ System.out.println("Shape 생성"); } } class Circle extends Shape{ int radius; public Circle(int radius){ System.out.println("Circle 생성"); this.radius=radius; System.out.println("1"); super.x=0; super.y=0; } double getArea(){ return 3.14*radius*radius; } } public class CircleTest { public static void main(String[] args) { Circle circle = new Circle(10); circle.getArea(); } }
extends - 상속에서 물려받는 것 super - 부모 클래스에서 가져오는 것
 
  1. 자식 클래스 객체 안에는 부모 클래스에서 상속된 부분 포함 → 자식 클래스 안의 부모 클래스 부분을 초기화하기 위해 부모 클래스 생성자 호출
  1. 생성자 호출 순서 부모 클래스의 생성자 → 자식 클래스의 생성자
 
  • 명시적인 호출
class Base01 { public Base01(){ System.out.println("Base01 생성자()"); } } class Derived01 extends Base { public Derived01(){ super(); System.out.println("Derived01 생성자()"); } } public class TestSuper { public static void main(String[] args) { new Derived01(); } }
자식 클래스의 생성자에서 명시적으로 부모 클래스 호출 가능 → super 키워드로 호출
  • 묵시적인 호출
class Base{ public Base(){ System.out.println("Base() 생성자"); } } class Derived extends Base{ public Derived(){ System.out.println("Derived() 생성자"); } } public class TestExtends { public static void main(String[] args) { Derived r = new Derived(); } }
자바는 명시적 호출 X → 자식 클래스의 객체 생성 시 자동적으로 부모 클래스의 기본 생성자 호출
 

용어 정의

오버라이딩: 부모 클래스의 메소드를 무시하고 덮어씌운다는 의미 / 메소드명, 매개 변수, 반환형 동일
오버라이딩: 부모 클래스의 메소드를 무시하고 덮어씌운다는 의미 / 메소드명, 매개 변수, 반환형 동일

메소드 오버라이딩

class Shape{ public void draw(){ System.out.println("Shape"); } } class Circle extends Shape{ @Override public void draw(){ System.out.println("Circle을 그립니다."); } } class Rectangle extends Shape{ @Override public void draw(){ System.out.println("Rectangle을 그립니다."); } } class Triangle extends Shape{ @Override public void draw(){ System.out.println("Triangle을 그립니다."); } } public class ShapeTest01 { public static void main(String[] args) { Rectangle s = new Rectangle(); s.draw(); Triangle t = new Triangle(); t.draw(); } }
- Rectangle 클래스 객체에서 draw( )가 호출되면 해당 클래스 안에 오버라이딩된 draw( )가 호출 - 부모 클래스의 메소드와 자식 클래스의 메소드가 일치해야 오버라이딩으로 처리 가능
class Animal { void speak() { System.out.println("멍멍"); } void run() { System.out.println("달린다."); } } class Cat extends Animal{ @Override void speak() { System.out.println("야옹"); } } public class AnimalEx01 { public static void main(String[] args) { Animal c1 = new Cat(); c1.speak(); c1.run(); } }
Animal c1 = new Cat; 
Cat c1 = new Cat;
Animal c1 = new Cat; Cat c1 = new Cat;
c1 → Animal, Cat  둘 중 하나 선택 가능
⇒ 메모리에 둘 다 떠있기에 가능
c1 → Animal, Cat 둘 중 하나 선택 가능 ⇒ 메모리에 둘 다 떠있기에 가능
super 사용으로 부모 클래스 접근
super 사용으로 부모 클래스 접근
class Shape01{ public void draw(){ System.out.println("Shape 중의 하나를 그릴 예정"); } } class Circle01 extends Shape01{ @Override public void draw(){ super.draw(); System.out.println("Circle을 그립니다."); } } public class ShapeTest02 { public static void main(String[] args) { Circle s = new Circle(); s.draw(); } }
부모 클래스의 메소드 호출 후 자신이 필요한 부분 추가할 경우
💡
abstract 추상 클래스 - 상속하면서 구체적인 클래스를 띄울 때 사용하며 독립적인 사용 불가
abstract class Judge{ public abstract void questioning(); } abstract class Witness{ public abstract void answer(); } class King01 extends Judge{ public void questioning(){ System.out.println("왕은 심문한다."); } } class Queen01 extends Judge{ public void questioning(){ System.out.println("왕비는 심문한다."); } } class hatSeller01 extends Witness{ public void answer(){ System.out.println("모자장수는 대답한다."); } } class rabbit01 extends Witness{ public void answer(){ System.out.println("토끼는 대답한다."); } } class Alice extends Witness{ public void answer(){ System.out.println("엘리스는 대답한다."); } } public class AliceApp01 { public static void main(String[] args) { Judge u1 = new Queen01(); Witness u2 = new rabbit01(); u1.questioning(); u2.answer(); } }
상속을 사용할 때 구체적인 애를 띄울 때 같이 뜬다. 독립적으로는 못 띄움 오브젝트가 아니며 new 불가능

다형성

class Animal { void speak() { System.out.println("멍멍"); } void run() { System.out.println("달린다."); } } class Cat extends Animal{ @Override void speak() { System.out.println("야옹"); } } public class AnimalEx01 { public static void main(String[] args) { Animal c1 = new Cat(); // [Cat, Animal] c1.speak(); c1.run(); } }
Cat c1 = new Cat( ); / Animal c1 = new Cat; → new Cat은 Cat, Animal의 이름에 모두 포함
💡
instanseof 연산자 - 변수가 가리키는 객체의 실제 타입 출력
💡
종단 클래스 (final class) - 보안상의 이유로 사용 ↳ 상속시킬 수 없는 클래스 ex) final class String
 
상속 형변환
상속 형변환
interface Remocon { void on(); void off(); } class SamsungRemocon implements Remocon { @Override public void on() { System.out.println("삼성 리모컨 on"); } @Override public void off() { System.out.println("삼성 리모컨 off"); } } class LgRemocon implements Remocon { @Override public void on() { System.out.println("LG 리모컨 on"); } @Override public void off() { System.out.println("LG 리모컨 off"); } } /** * 작성자 : 홍길동 * 날짜 : 2023.12.26 * 구현체 : SamsungRemocon, LgRemocon */ class CommonRemocon{ private Remocon r; public CommonRemocon(Remocon r) { this.r = r; } public void on(){ r.on(); } public void off(){ r.off(); } } public class InterEx01 { public static void main(String[] args) { CommonRemocon cr = new CommonRemocon(new SamsungRemocon()); cr.on(); } }
 
 

구성 (composition)

  • 구성 - 클래스가 다른 클래스의 인스턴스를 클래스의 필드로 가지는 디자인 기법
  • 상속 - 한 객체가 클래스를 상속받아서 부모 객체의 속성과 동작을 획득 가능한 기법
    • ⇒ 공통점: 클래스를 연결하여 코드의 재사용성 제공
is - a 관계
A는 B의 일종이다.
상속 사용 → 단방향이기 때문
구성
하나의 객체가 다른 객체의 부품
has - a 관계
~는 ~를 가지고 있다.
객체 지향 프로그래밍에서 구성 또는 집합의 의미
집합
하나의 객체가 다른 객체 소유
 
Share article

from-web-developer