πŸ“– 상속에 λŒ€ν•˜μ—¬


κ°•μ˜μ‹œκ°„μ— 배운 상속 κ°œλ…μ— μΆ”κ°€λ‘œ κ³΅λΆ€ν•œ λ‚΄μš©μ„ 정리해본닀 ✍️

상속

λ¨Όμ € μƒμ†μ΄λž€ ? 기쑴의 클래슀λ₯Ό μž¬μ‚¬μš©ν•˜μ—¬ μƒˆλ‘œμš΄ 클래슀λ₯Ό μž‘μ„±ν•˜λŠ” 것이닀.
예제λ₯Ό 보λͺ…μ„œ μƒμ†μ˜ ν•„μš”μ„±μ„ νŒŒμ•…ν•΄λ³΄μž !

Example

μΉ΄νŽ˜μ—μ„œ 컀피와 μ°¨λ₯Ό νŒλ§€ν•œλ‹€.
컀피와 μ°¨λ₯Ό μ€€λΉ„ν•˜λŠ” 과정을 μ‚΄νŽ΄λ³΄μž.

컀피

  • 물을 끓인닀.
  • μ»€ν”Όλ¨Έμ‹ μœΌλ‘œ 컀피λ₯Ό λ‚΄λ¦°λ‹€.
  • 컡에 λΆ“λŠ”λ‹€.
  • 섀탕과 우유λ₯Ό μΆ”κ°€ν•œλ‹€.

    μ°¨

  • 물을 끓인닀.
  • μ°¨ 티백을 λ‹΄κ·Όλ‹€.
  • 컡에 λΆ“λŠ”λ‹€.
  • 레λͺ¬μ„ μΆ”κ°€ν•œλ‹€.

κ·Έλ ‡λ‹€λ©΄ 각각의 과정듀을 μ½”λ“œλ‘œ κ΅¬ν˜„ν•΄λ³Έλ‹€.

public class Coffee {
    void prepareRecipe() {
        boilWater();
        brewCoffeeMachine();
        pourInCup();
        addSugarAndMilk();
    }

    public void boilWater() {
        System.out.println("물을 끓인닀.");
    }

    public void brewCoffeeMachine() {
        System.out.println("μ»€ν”Όλ¨Έμ‹ μœΌλ‘œ 컀피λ₯Ό λ‚΄λ¦°λ‹€.");
    }

    public void pourInCup() {
        System.out.println("컡에 λΆ“λŠ”λ‹€.");
    }

    public void addSugarAndMilk() {
        System.out.println("섀탕과 우유λ₯Ό μΆ”κ°€ν•œλ‹€.");
    }
}
public class Tea {
    void prepareRecipe() {
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }

    public void boilWater() {
        System.out.println("물을 끓인닀.");
    }

    public void steepTeaBag() {
        System.out.println("티백을 λ‹΄κ·Όλ‹€.");
    }

    public void pourInCup() {
        System.out.println("컡에 λΆ“λŠ”λ‹€.");
    }

    public void addLemon() {
        System.out.println("레λͺ¬μ„ μΆ”κ°€ν•œλ‹€.");
    }
}

Coffee ν΄λž˜μŠ€μ™€ Tea 클래슀λ₯Ό 비ꡐ해보면 μ΄μƒν•œ 점을 λŠλ‚„ 수 μžˆλ‹€.
prepareRecipe(), boilWater(), pourInCup()
이 세가지 λ©”μ†Œλ“œλŠ” κ³΅ν†΅λœ κΈ°λŠ₯을 ν•˜μ§€ μ•ŠλŠ”κ°€??

κ·Έλ ‡λ‹€λ©΄ β€œμ΄ μ€‘λ³΅λœ 뢀뢄을 μ–΄λ–»κ²Œ μ œκ±°ν•˜λŠλƒ?”에 λŒ€ν•œ ν•΄λ‹΅μœΌλ‘œ
λ°”λ‘œ 상속이 λ‚˜μ˜¨λ‹€.

κ·Έλ ‡λ‹€λ©΄ 두 ν΄λž˜μŠ€μ—μ„œ κ³΅ν†΅λœ 뢀뢄을 μΆ”μΆœν•˜μ—¬ λΆ€λͺ¨ 클래슀λ₯Ό λ§Œλ“€μ–΄λ³Έλ‹€.

public class Beverage {
    protected void boilWater() {
        System.out.println("물을 끓인닀.");
    }

    protected void pourInCup() {
        System.out.println("컡에 λΆ“λŠ”λ‹€.");
    }
}

κ³΅ν†΅λœ κΈ°λŠ₯을 묢은 λΆ€λͺ¨ 클래슀인 Beverageλ₯Ό 상속 λ°›λŠ” 각각의 클래슀λ₯Ό λ§Œλ“€μ–΄λ³Έλ‹€.

public class Coffee extends Beverage {
    void prepareRecipe() {
        boilWater();
        brewCoffeeMachine();
        pourInCup();
        addSugarAndMilk();
    }

    public void brewCoffeeMachine() {
        System.out.println("ν•„ν„°λ₯Ό ν™œμš©ν•΄ 컀피λ₯Ό λ‚΄λ¦°λ‹€.");
    }

    public void addSugarAndMilk() {
        System.out.println("섀탕과 우유λ₯Ό μΆ”κ°€ν•œλ‹€.");
    }
}
public class Tea extends Beverage {
    void prepareRecipe() {
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }

    public void steepTeaBag() {
        System.out.println("티백을 λ‹΄κ·Όλ‹€.");
    }

    public void addLemon() {
        System.out.println("레λͺ¬μ„ μΆ”κ°€ν•œλ‹€.");
    }
}

extends

μ΄λ ‡κ²Œ 상속은 extends ν‚€μ›Œλ“œλ‘œ 이루어 진닀.
상속을 ν•  경우 멀버 ν•„λ“œμ™€ λ©”μ†Œλ“œλ₯Ό ν•˜μœ„ ν΄λž˜μŠ€μ—μ„œ κ·ΈλŒ€λ‘œ μƒμ†ν•˜κ²Œ λ˜λŠ”λ°,
ν‚€μ›Œλ“œμ˜ μ˜λ―ΈλŒ€λ‘œ μžμ‹ ν΄λž˜μŠ€κ°€ 쑰상 클래슀λ₯Ό ν™•μž₯ν•˜λŠ” 의미둜 해석할 수 μžˆλ‹€.
μ—¬κΈ°μ„œ 주의점 !

  • μƒμ„±μžμ™€ μ΄ˆκΈ°ν™” λΈ”λŸ­μ€ μƒμ†λ˜μ§€ μ•ŠλŠ”λ‹€. λ©€λ²„λ§Œ μƒμ†λœλ‹€.
  • μžμ‹ 클래슀의 멀버 κ°œμˆ˜λŠ” 쑰상 ν΄λž˜μŠ€λ³΄λ‹€ 항상 κ°™κ±°λ‚˜ λ§Žλ‹€.
  • private, defaultλŠ” μƒμ†λ˜μ§€ μ•ŠλŠ”λ‹€κΈ° λ³΄λ‹€λŠ” 상속은 λ°›μ§€λ§Œ μžμ‹ ν΄λž˜μŠ€λ‘œλΆ€ν„°μ˜ 접근이 μ œν•œλœλ‹€.
  • μžλ°”μ—μ„œλŠ” 닀쀑 상속을 μ§€μ›ν•˜μ§€ μ•ŠλŠ”λ‹€.

μ˜€λ²„λΌμ΄λ”©

쑰상 ν΄λž˜μŠ€λ‘œλΆ€ν„° 상속 받은 λ©”μ„œλ“œμ˜ λ‚΄μš©μ„ λ³€κ²°ν•˜λŠ” 것
μžμ‹ ν΄λž˜μŠ€μ—μ„œ λΆ€λͺ¨ 클래슀 λ©”μ„œλ“œλ₯Ό 맞게 λ³€κ²½ν•˜λŠ” 경우 μ˜€λ²„λΌμ΄λ”©μ„ ν•œλ‹€.

μ˜€λ²„λΌμ΄λ”©μ˜ 쑰건

μžμ‹ 클래슀의 λ©”μ†Œλ“œμ—μ„œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œμ™€ λ‹€μŒ 쑰건듀이 κ°™μ•„μ•Ό ν•œλ‹€.

  • λ©”μ†Œλ“œ λͺ…
  • λ§€κ°œλ³€μˆ˜
  • λ°˜ν™˜νƒ€μž…

    μ˜€λ²„λΌμ΄λ”© 주의점

  • μ ‘κ·Ό μ œμ–΄μžλ₯Ό 쑰상 클래슀의 λ©”μ„œλ“œλ³΄λ‹€ 쒁은 λ²”μœ„λ‘œ λ³€κ²½ν•  수 μ—†λ‹€.
  • μ˜ˆμ™ΈλŠ” 쑰상 클래슀의 λ©”μ„œλ“œλ³΄λ‹€ 많이 μ„ μ–Έν•  수 μ—†λ‹€.
  • μΈμŠ€ν„΄μŠ€λ©”μ„œλ“œλ₯Ό static λ©”μ„œλ“œ, λ˜λŠ” κ·Έ λ°˜λŒ€λ‘œ λ³€κ²½ν•  수 μ—†λ‹€.

πŸ€” 쑰상 ν΄λž˜μŠ€μ— μ •μ˜λœ static λ©”μ„œλ“œλ₯Ό μžμ† ν΄λž˜μŠ€μ—μ„œ λ˜‘κ°™μ€ μ΄λ¦„μ˜ static λ©”μ„œλ“œλ‘œ μ •μ˜ν•  수 μžˆλ‚˜?
κ°€λŠ₯은 ν•˜μ§€λ§Œ 각 ν΄λž˜μŠ€μ— λ³„κ°œμ˜ static λ©”μ„œλ“œλ₯Ό μ •μ˜ν•œ 것일 뿐 μ˜€λ²„λΌμ΄λ”©μ΄ μ•„λ‹ˆλ‹€.

μƒμ†μ˜ μž₯점

  • μ€‘λ³΅λœ μ½”λ“œλ₯Ό 쀄일 수 μžˆλ‹€.
  • 곡톡적 ν•„λ“œλ₯Ό μΆ”κ°€ν•˜κ±°λ‚˜, μˆ˜μ •ν•  λ•Œ λΆ€λͺ¨ ν΄λž˜μŠ€μ—λ§Œ μž‘μ—…ν•΄μ£Όλ©΄ λœλ‹€.

ν΄λž˜μŠ€κ°„μ˜ 관계

상속을 톡해 ν΄λž˜μŠ€κ°„μ— 관계λ₯Ό λ§Ίμ–΄μ£ΌλŠ”λ°,
μ΄λ•Œ μƒκΈ°λŠ” 관계λ₯Ό λͺ‡ 가지 μœ ν˜•μœΌλ‘œ λ‚˜λˆ λ³Ό 수 μžˆλ‹€.

is-a 관계 (is a relationship)

is-a κ΄€κ³„λŠ” 일반적인 κ°œλ…κ³Ό ꡬ체적인 κ°œλ…κ³Όμ˜ 관계λ₯Ό λ§ν•œλ‹€.
μ—¬κΈ°μ„œ 일반적인 κ°œλ… ν΄λž˜μŠ€λŠ” μƒμœ„ 클래슀인 λΆ€λͺ¨ 클래슀λ₯Ό λœ»ν•˜κ³ ,
ꡬ체적인 κ°œλ… ν΄λž˜μŠ€λŠ” ν•˜μœ„ 클래슀인 μžμ‹ 클래슀λ₯Ό λœ»ν•œλ‹€.

말 κ·ΈλŒ€λ‘œ β€œ~은 ~이닀.β€λΌλŠ” λ¬Έμž₯이 μ„±λ¦½λ˜μ–΄μ•Ό ν•œλ‹€.

  • Example ```java public class Person{ String name; int age; }

public class Student extends Person{ int number; int major; }

μœ„ μ˜ˆμ œμ—μ„œλŠ” Student ν΄λž˜μŠ€κ°€ Person 클래슀λ₯Ό 상속받고 μžˆλ‹€.  
"학생은 μ‚¬λžŒμ΄λ‹€."처럼 μ΄λŸ¬ν•œ 관계λ₯Ό is-a 관계라고 ν•œλ‹€.

#### has-a 관계 (composition)
has-a κ΄€κ³„λŠ” ν•œ ν΄λž˜μŠ€κ°€ λ‹€λ₯Έ 클래슀λ₯Ό μ†Œμœ ν•œ 관계이닀.

말 κ·ΈλŒ€λ‘œ **"~은 ~을 가지고 μžˆλ‹€."λΌλŠ” λ¬Έμž₯이 μ„±λ¦½λ˜μ–΄μ•Ό ν•œλ‹€.**
* Example
```java
class Circle {
    Point point;
    int r;
} 

class Point {
    int x;
    int y;
}

μœ„ μ˜ˆμ œμ—μ„œλŠ” Point 클래슀λ₯Ό μž¬μ‚¬μš©ν•΄μ„œ Circle 클래슀λ₯Ό μž‘μ„±ν–ˆλ‹€.
ν•˜λ‚˜μ˜ κ±°λŒ€ν•œ 클래슀λ₯Ό μž‘μ„±ν•˜λŠ” 것보닀 λ‹¨μœ„λ³„λ‘œ μ—¬λŸ¬ 개의 클래슀λ₯Ό μž‘μ„±ν•œ ν›„,
이 λ‹¨μœ„ ν΄λž˜μŠ€λ“€μ„ ν¬ν•¨κ΄€κ³„λ‘œ μž¬μ‚¬μš©ν•˜λ©΄ 보닀 κ°„κ²°ν•˜κ³  μ†μ‰½κ²Œ 클래슀λ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.
또 μž‘μ„±λœ λ‹¨μœ„ ν΄λž˜μŠ€λ“€μ€ λ‹€λ₯Έ 클래슀λ₯Ό μž‘μ„±ν•˜λŠ”λ° μž¬μ‚¬μš©λ  수 μžˆλ‹€.

β€œ~은 ~이닀.” λ˜λŠ” β€œ~은 ~을 가지고 μžˆλ‹€.” λ¬Έμž₯을 λ§Œλ“€μ–΄λ³΄κ³ 
더 μ ν•©ν•œ 관계λ₯Ό κ΅¬ν˜„ν•˜λŠ” 것이 μ’‹λ‹€.

(μ΄νŽ™ν‹°λΈŒ μžλ°”μ— β€œμƒμ†λ³΄λ‹¨ μ‘°ν•©β€μ΄λΌλŠ” κ°œλ…μ΄ 있던데 이 뢀뢄도 정리해보아야겠닀.)

μΊμŠ€νŒ…

πŸ€” μΊμŠ€νŒ…μ΄λž€ ? νƒ€μž…μ„ λ³€ν™˜ν•˜λŠ” 것을 λ§ν•˜λ©°, ν˜•λ³€ν™˜μ΄λΌκ³ λ„ ν•œλ‹€.
κΈ°λ³Έν˜• λ³€μˆ˜μ™€ 같이 μ°Έμ‘°λ³€μˆ˜λ„ ν˜•λ³€ν™˜μ΄ κ°€λŠ₯ν•œλ°, 상속 관계에 μžˆλŠ” 클래슀 μ‚¬μ΄μ—μ„œλ§Œ κ°€λŠ₯ν•˜λ‹€.

μ΄λ•Œ, κΈ°λ³Έν˜• μ°Έμ‘°ν˜• λ³€μˆ˜μ˜ ν˜•λ³€ν™˜μ—μ„œ μžμ† νƒ€μž…μ˜ μ°Έμ‘°λ³€μˆ˜λ₯Ό μ‘°μƒνƒ€μž…μœΌλ‘œ
ν˜•λ³€ν™˜ν•˜λŠ” κ²½μš°μ—λŠ” ν˜•λ³€ν™˜μ„ μƒλž΅ν•  수 μžˆλ‹€.

μ—…μΊμŠ€νŒ…

μžμ‹ 클래슀의 μ°Έμ‘°λ³€μˆ˜λ₯Ό λΆ€λͺ¨ 클래슀의 μ°Έμ‘°λ³€μˆ˜λ‘œ λ³€ν™˜ν•˜λ©°, ν˜•λ³€ν™˜ μƒλž΅μ΄ κ°€λŠ₯ν•˜λ‹€.
λΆ€λͺ¨ 클래슀의 μ°Έμ‘° λ³€μˆ˜κ°€ μžμ‹ 클래슀둜 κ°μ²΄ν™”λœ μΈμŠ€ν„΄μŠ€λ₯Ό 가리킬 수 μžˆλ‹€.
λ•Œλ¬Έμ— λ‹€ν˜•μ„±μ„ μœ„ν•΄ μ‚¬μš©λœλ‹€.
ex) 학생은 μ‚¬λžŒμ΄λ‹€.

μœ„μ—μ„œ λ‹€λ€˜λ˜ Student 예제둜 ν™•μΈν•΄λ³΄μž.

// μ°Έμ‘°λ³€μˆ˜ studentλ₯Ό μ΄μš©ν•˜λ©΄ number, major에 μ ‘κ·Ό κ°€λŠ₯
Student student = new Student();

// 레퍼런슀 person을 μ΄μš©ν•˜λ©΄ Student 객체의 멀버 쀑 
// 였직 Person 클래슀의 λ©€λ²„λ§Œ 접근이 κ°€λŠ₯ν•˜λ‹€.
Person person = student;
person.name = "amazzi";
person.age = 10;

// μ•„λž˜ λ¬Έμž₯은 컴파일 였λ₯˜κ°€ λ‚œλ‹€.
person.number = "12345678";

이처럼 μ—…μΊμŠ€νŒ…μ„ ν•˜κ²Œλ˜λ©΄ λΆ€λͺ¨ 클래슀의 ν•„λ“œ, λ©”μ„œλ“œμ—λ§Œ 접근이 κ°€λŠ₯ν•˜λ‹€.

λ‹€μš΄μΊμŠ€νŒ…

μžμ‹ 클래슀의 μ°Έμ‘°λ³€μˆ˜λ₯Ό μžμ‹ νƒ€μž…μ˜ μ°Έμ‘°λ³€μˆ˜λ‘œ λ³€ν™˜ν•˜λ©°, ν˜•λ³€ν™˜ μƒλž΅μ΄ λΆˆκ°€λŠ₯ν•˜λ‹€.
μžμ‹ μ˜ κ³ μœ ν•œ νŠΉμ„±μ„ μžƒμ€ μ„œλΈŒ 클래슀의 객체λ₯Ό λ‹€μ‹œ 볡ꡬ μ‹œμΌœμ£ΌλŠ” 것을 λ§ν•œλ‹€. (μ—…μΊμŠ€νŒ… 볡ꡬ?)

// μ—…μΊμŠ€νŒ… λ¨Όμ €
Person person = new Student();

// λ‹€μš΄μΊμŠ€νŒ…
Student student = (Student) person;

// Ok
student.name = "amazzi";
student.number = "12345678";

κΌ­ μ—…μΊμŠ€νŒ…μ΄ λ¨Όμ € 선행이 λ˜μ–΄μ•Ό ν•œλ‹€.
λ§Œμ•½ λ‹€μŒκ³Ό 같은 κ²½μš°λŠ” 컴파일 였λ₯˜λŠ” λ‚˜μ§€ μ•Šμ§€λ§Œ ClassCastException λŸ°νƒ€μž„ 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

Student student = (Student) new Person();