[JAVA] 상속 (Inheritance)

chaeyeongΒ·2025λ…„ 2μ›” 2일

μžλ°” 이둠

λͺ©λ‘ 보기
6/9

1. μƒμ†μ΄λž€?

πŸ’‘ μžμ‹(클래슀)이 상속받고 싢은 λΆ€λͺ¨(클래슀)λ₯Ό μ„ νƒν•΄μ„œ λ¬Όλ €λ°›λŠ”λ‹€. 이 λ•Œ, μƒμ†λ°›λŠ” 클래슀λ₯Ό μžμ‹ 클래슀, ν•˜μœ„ 클래슀(μ„œλΈŒ 클래슀)라고 λΆ€λ₯Έλ‹€. 상속을 ν•΄μ£ΌλŠ” 클래슀λ₯Ό λΆ€λͺ¨ 클래슀(μƒμœ„ 클래슀 λ˜λŠ” 슈퍼 클래슀)라고 ν•œλ‹€.

1-1. μƒμ†μ˜ λŒ€μƒ

  • μžμ‹ ν΄λž˜μŠ€κ°€ λΆ€λͺ¨ ν΄λž˜μŠ€λ‘œλΆ€ν„° 상속을 λ°›κ²Œ 되면 λΆ€λͺ¨ 클래슀의 ν•„λ“œμ™€ λ©”μ„œλ“œλ₯Ό λ¬Όλ €λ°›κ²Œ λœλ‹€.

  • 단, μ ‘κ·Όμ œμ–΄μžκ°€ privateλ₯Ό κ°€μ§€λŠ” ν•„λ“œλ‚˜ λ©”μ†Œλ“œλŠ” 상속이 λΆˆκ°€ν•˜κ³ , νŒ¨ν‚€μ§€κ°€ λ‹€λ₯Ό 경우 μ ‘κ·Όμ œμ–΄μžκ°€ default인 κ²½μš°λ„ 상속이 λΆˆκ°€ν•˜λ‹€.

1-2. μƒμ†μ˜ μž₯점

  • μ€‘λ³΅λœ μ½”λ“œλ₯Ό 쀄일 수 μžˆλ‹€.

  • μœ μ§€ λ³΄μˆ˜κ°€ νŽΈλ¦¬ν•˜λ‹€.

  • 톡일성이 있고 λ‹€ν˜•μ„±μ„ κ΅¬ν˜„ν•  수 μžˆλ‹€.

1-3. μƒμ†μ˜ 방법

μžμ‹ 클래슀의 이름 뒀에 extends ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜κ³  λΆ€λͺ¨ 클래슀의 이름을 μ λŠ”λ‹€

public class A extends B {...}

1-4. μƒμ†μ˜ νŠΉμ§•

πŸ’‘ μžλ°”μ—μ„œλŠ” μžμ‹ ν΄λž˜μŠ€κ°€ μ—¬λŸ¬ λΆ€λͺ¨λ‘œλΆ€ν„° 닀쀑 상속을 λ°›λŠ” 것이 λΆˆκ°€λŠ₯ν•˜λ‹€. 즉, 단 ν•œ 개의 λΆ€λͺ¨ ν΄λž˜μŠ€λ‘œλΆ€ν„°μ˜ 단일 μƒμ†λ§Œ ν—ˆμš© λœλ‹€. ν•˜μ§€λ§Œ λΆ€λͺ¨ ν΄λž˜μŠ€λŠ” μ—¬λŸ¬ 개의 μžμ‹ ν΄λž˜μŠ€μ—κ²Œ 상속이 κ°€λŠ₯ν•˜λ‹€.

❌ λΆˆκ°€λŠ₯
class A extends B, C {...}

⭕️ κ°€λŠ₯
class A extends B {...}
class C extends B {...}
class B extends C {...}
class A extneds B {...}

1-5. μƒμ†μ˜ ν™œμš©

class A {
	String aField = "클래슀 A의 ν•„λ“œ";
    public void aMethod() {
    	System.out.println(aField);
    }
}
class B extends A {
	String bField = "클래슀 B의 ν•„λ“œ";
    public void bMethod() {
    	System.out.println(aField); // λΆ€λͺ¨ 클래슀의 ν•„λ“œ 
        System.out.println(bField); // 본인 클래슀의 ν•„λ“œ 
    }    
}
class C extends B {
	String cField = "클래슀 C의 ν•„λ“œ";
    public void cMethod() {
    	System.out.println(aField); // μ‘°λΆ€λͺ¨ 클래슀의 ν•„λ“œ 
        System.out.println(bField); // λΆ€λͺ¨ 클래슀의 ν•„λ“œ 
        System.out.println(cField); // 본인 클래슀의 ν•„λ“œ 
    }
}
publuc class Main {
	publuc static void main(String[] args) {
    	A a = new A();
        a.aMethod(); // 본인 λ©”μ†Œλ“œ 
        
        B b = new B();
        b.aMethod(); // λΆ€λͺ¨ λ©”μ†Œλ“œ
        b.bMethod(); // 본인 λ©”μ†Œλ“œ
        
        C c = new C();
        c.aMethod(); // μ‘°λΆ€λͺ¨ λ©”μ†Œλ“œ
        c.bMethod(); // λΆ€λͺ¨ λ©”μ†Œλ“œ
        c.cMethod(); // 본인 λ©”μ†Œλ“œ
    }
}

1-6. super

πŸ’‘ super ν‚€μ›Œλ“œλŠ” λΆ€λͺ¨ ν΄λž˜μŠ€λ‘œλΆ€ν„° 상속받은 ν•„λ“œλ‚˜ λ©”μ†Œλ“œλ₯Ό μžμ‹ ν΄λž˜μŠ€μ—μ„œ μ°Έμ‘°ν•˜λŠ” 데에 μ‚¬μš©ν•˜λŠ” μ°Έμ‘°λ³€μˆ˜μ΄λ‹€.

➑️ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μ˜ 이름과 μ§€μ—­ λ³€μˆ˜μ˜ 이름이 같을 경우 μΈμŠ€ν„΄μŠ€ λ³€μˆ˜ μ•žμ— this ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ ꡬ뢄할 수 μžˆλŠ”λ°, 이와 λ§ˆμ°¬κ°€μ§€λ‘œ λΆ€λͺ¨ 클래슀의 멀버와 μžμ‹ 클래슀의 멀버 이름이 같을 경우 super ν‚€μ›Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ κ΅¬λΆ„ν•œλ‹€.

  • super μ°Έμ‘° λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ—¬ λΆ€λͺ¨ 클래슀의 멀버에 μ ‘κ·Όν•  수 μžˆλ‹€. this와 λ§ˆμ°¬κ°€μ§€λ‘œ super μ°Έμ‘° λ³€μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” λŒ€μƒλ„ μΈμŠ€ν„΄μŠ€ λ©”μ†Œλ“œ 뿐이며, 클래슀 λ©”μ†Œλ“œμ—μ„œλŠ” μ‚¬μš©ν•  수 μ—†λ‹€.
class B { int a = 10; }

class A extends B {
	int a = 20;
	void display() {
    	System.out.println(a); // μ‹€ν–‰κ²°κ³Ό: 20
        System.out.println(this.a); // μ‹€ν–‰κ²°κ³Ό: 20
        System.out.println(super.a); // μ‹€ν–‰κ²°κ³Ό: 10
    }
}
publuc class Main {
	public static void main(String[] args) {
    	A a = new A();
        a.display();
    }
}

2. λ©”μ†Œλ“œ μ˜€λ²„λΌμ΄λ”© (Method Overriding)

πŸ’‘ λ©”μ†Œλ“œ μ˜€λ²„λΌμ΄λ”©μ΄λž€ 상속받은 λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό μž¬μ •μ˜ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€.

➑️ 주둜 μžμ‹ ν΄λž˜μŠ€μ—μ„œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό μˆ˜μ •ν•΄μ•Ό ν•  λ•Œ μ‚¬μš©λœλ‹€. 일반 클래슀의 상속 κ΄€κ³„μ—μ„œλŠ” 많이 μ‚¬μš©λ˜μ§€ μ•Šκ³  μΆ”μƒν΄λž˜μŠ€λ‚˜ μΈν„°νŽ˜μ΄μŠ€μ—μ„œ ν•„μˆ˜μ μœΌλ‘œ μ‚¬μš©λ˜λŠ” κ°œλ…μ΄λ‹€. ν•„μš”μ‹œ super ν‚€μ›Œλ“œλ‘œ λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€.

2-1. μ˜€λ²„λΌμ΄λ”© 쑰건

  • μ˜€λ²„λΌμ΄λ”©μ€ λ©”μ†Œλ“œμ˜ λ™μž‘λ§Œμ„ μž¬μ •μ˜ν•˜λŠ” κ²ƒμœΌλ‘œ, λ©”μ†Œλ“œμ˜ μ„ μ–ΈλΆ€λŠ” κΈ°μ‘΄ λ©”μ†Œλ“œμ™€ κ°™μ•„μ•Ό ν•œλ‹€.

    • 단, λ©”μ†Œλ“œμ˜ λ°˜ν™˜ νƒ€μž…μ€ λΆ€λͺ¨ 클래슀의 λ°˜ν™˜ νƒ€μž…μœΌλ‘œ νƒ€μž… λ³€ν™˜ν•  수 μžˆλ‹€λ©΄ λ³€κ²½ν•  수 μžˆλ‹€.
  • λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ³΄λ‹€ μ ‘κ·Ό μ œμ–΄μžλ₯Ό 더 쒁은 λ²”μœ„λ‘œ λ³€κ²½ν•  수 μ—†λ‹€.

  • λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œλ³΄λ‹€ 더 큰 λ²”μœ„μ˜ μ˜ˆμ™Έλ₯Ό μ„ μ–Έν•  수 μ—†λ‹€.

class B {
	void display() {
    	System.out.println("λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œ");
    }
}
class A extends B {
	void display() {
    	System.out.println("μžμ‹ 클래슀의 λ©”μ†Œλ“œ");
    }
}
public class Main {
	public static void main(String[] args) {
    	B b1 = new B();
        b1.display(); // μ‹€ν–‰κ²°κ³Ό: λΆ€λͺ¨ 클래슀의 λ©”μ†Œλ“œ
        
        A a = new A();
        a1.display(); // μ‹€ν–‰κ²°κ³Ό: μžμ‹ 클래슀의 λ©”μ†Œλ“œ
        
        B b2 = new A();
        b2.display(); // A a2 = new B(); 
        //μ‹€ν–‰κ²°κ³Ό: μžμ‹ 클래슀의 λ©”μ†Œλ“œ
    }
}

➑️ μœ„μ˜ μ˜ˆμ œμ—μ„œ μ„Έ λ²ˆμ§Έμ™€ 같은 μΈμŠ€ν„΄μŠ€ μ°Έμ‘°κ°€ κ°€λŠ₯ν•œ μ΄μœ λŠ” λ‹€ν˜•μ„±(polymorphism) λ•Œλ¬Έμ΄λ‹€.

2-2. 좔상 클래슀 (Abstract Class)

ν•˜λ‚˜ μ΄μƒμ˜ 좔상 λ©”μ†Œλ“œλ₯Ό ν¬ν•¨ν•˜λŠ” 클래슀λ₯Ό 좔상 클래슀(Abstract Class)라고 ν•œλ‹€.

  • 좔상 ν΄λž˜μŠ€λŠ” 객체 μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ€‘μš”ν•œ νŠΉμ§•μΈ λ‹€ν˜•μ„±μ„ κ°€μ§€λŠ” λ©”μ†Œλ“œμ˜ 집합을 μ •μ˜ν•  수 μžˆλ„λ‘ ν•΄μ€€λ‹€.

  • 좔상 ν΄λž˜μŠ€λŠ” λ™μž‘μ΄ μ •μ˜λ˜μ–΄ μžˆμ§€ μ•Šμ€ 좔상 λ©”μ†Œλ“œλ₯Ό ν¬ν•¨ν•˜κ³  μžˆμœΌλ―€λ‘œ μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μ—†λ‹€.

  • λ¨Όμ € 상속을 톡해 μžμ‹ 클래슀λ₯Ό λ§Œλ“€κ³ , μžμ‹ ν΄λž˜μŠ€μ—μ„œ 좔상 클래슀의 λͺ¨λ“  좔상 λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”© ν•΄μ•Ό μžμ‹ 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό 생성할 수 μžˆλ‹€.

  • abstract class 클래슀λͺ… { abstract λ°˜ν™˜νƒ€μž… λ©”μ†Œλ“œλͺ…(); }

abstract class Animal { abstract void sound(); }

class Cat extends Animal {
	void sound() {
    	System.out.println("λ―Έμ•Όμ˜Ή");
    }
}
class Dog extends Animal {
	void sound() {
    	System.out.println("멍멍");
    }
}
public class Main {
	public static void main(String[] args) {
    	Cat c = new Cat();
        c.sound(); // μ‹€ν–‰κ²°κ³Ό: λ―Έμ•Όμ˜Ή
        
        Dog d = new Dog(); 
        d.sound(); // μ‹€ν–‰κ²°κ³Ό: 멍멍
    }
}

➑️ 좔상 ν΄λž˜μŠ€λŠ” 좔상 λ©”μ†Œλ“œκ°€ ν¬ν•¨λœ 클래슀λ₯Ό 상속 λ°›λŠ” μžμ‹ ν΄λž˜μŠ€κ°€ λ°˜λ“œμ‹œ 좔상 λ©”μ†Œλ“œλ₯Ό κ΅¬ν˜„ν•˜λ„λ‘ ν•˜κΈ° μœ„ν•΄ μ‚¬μš©λœλ‹€.

3. λ‹€μ΄λ‚˜λ―Ή λ©”μ†Œλ“œ λ””μŠ€νŒ¨μΉ˜ (Dynamic Method Dispatch)

πŸ’‘ λ©”μ†Œλ“œ λ””μŠ€νŒ¨μΉ˜λž€ μ–΄λ–€ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν• μ§€ κ²°μ •ν•˜μ—¬ μ‹€μ œλ‘œ μ‹€ν–‰μ‹œν‚€λŠ” 과정이닀. μžλ°”λŠ” λŸ°νƒ€μž„ μ‹œμ— 객체λ₯Ό μƒμ„±ν•˜κ³ , 컴파일 μ‹œμ—λŠ” 생성할 객체 νƒ€μž…μ— λŒ€ν•œ μ •λ³΄λ§Œ λ³΄μœ ν•œλ‹€. λ‹€μ΄λ‚˜λ―Ή λ©”μ†Œλ“œ λ””μŠ€νŒ¨μΉ˜λŠ” μ»΄νŒŒμΌλŸ¬κ°€ 컴파일 λ‹¨κ³„μ—μ„œ μ–΄λ–€ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν• μ§€ λͺ¨λ₯΄λŠ” 경우 이닀. λ”°λΌμ„œ, λŸ°νƒ€μž„ μ‹œμ μ— ν• λ‹Ήλœ 객체의 νƒ€μž…μ„ 보고 λ©”μ†Œλ“œλ₯Ό μ‹€ν–‰ν•œλ‹€.


4. final

πŸ’‘ final은 였직 ν•œ 번만 ν• λ‹Ήν•  수 μžˆλŠ” entityλ₯Ό μ •μ˜ν•  λ•Œ μ‚¬μš©λœλ‹€. final둜 μ„ μ–Έλœ λ³€μˆ˜κ°€ ν• λ‹Ήλ˜λ©΄ 항상 같은 값을 κ°€μ§„λ‹€.

➑️ λ§Œμ•½ final λ³€μˆ˜κ°€ 객체λ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλ‹€λ©΄, κ·Έ 객체의 μƒνƒœκ°€ λ°”λ€Œμ–΄λ„ final λ³€μˆ˜λŠ” 맀번 λ™μΌν•œ λ‚΄μš©μ„ μ°Έμ‘°ν•œλ‹€.

4-1. final 클래슀

πŸ’‘ final둜 μ„ μ–Έν•œ ν΄λž˜μŠ€λŠ” μ΅œμ’… μƒνƒœκ°€ λ˜μ–΄λ²„λ¦¬κΈ° λ•Œλ¬Έμ— 상속을 ν•  수 μ—†λ‹€.

➑️ μ΄λŠ” λ³΄μ•ˆμ΄λ‚˜ νš¨μœ¨μ„±μ˜ μΈ‘λ©΄μ—μ„œ μž₯점이 μžˆλ‹€.


4-2. final λ©”μ†Œλ“œ

πŸ’‘ λΆ€λͺ¨ ν΄λž˜μŠ€μ— final νƒ€μž…μ˜ λ©”μ†Œλ“œκ°€ 있으면 μžμ‹ ν΄λž˜μŠ€λŠ” κ·Έ λ©”μ†Œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”© ν•  수 μ—†λ‹€.


final λ³€μˆ˜

πŸ’‘ final λ³€μˆ˜λŠ” 값을 ν•œ 번 ν• λ‹Ήν•˜λ©΄ μˆ˜μ •ν•  수 μ—†λ‹€. μ΄ˆκΈ°ν™”λŠ” 단 ν•œ 번만 κ°€λŠ₯ν•˜λ‹€. λ¨Όμ € μ„ μ–Έν•˜κ³  각각 λ‹€λ₯Έ 값을 가지도둝 μ΄ˆκΈ°ν™” ν•  μˆ˜λŠ” μžˆμ§€λ§Œ 이후에 μˆ˜μ •μ€ λΆˆκ°€λŠ₯ν•˜λ‹€. μ΄λŸ¬ν•œ ν˜•νƒœλ₯Ό blank final λ³€μˆ˜λΌκ³  ν•œλ‹€.

  • final λ³€μˆ˜ : λ©”λͺ¨λ¦¬μ˜ νš¨μœ¨μ„±μ„ 높이기 μœ„ν•΄ static λ³€μˆ˜μ™€ 같이 자주 쓰인닀.

  • blank final λ³€μˆ˜ : μΈμŠ€ν„΄μŠ€λ§ˆλ‹€ λ‹€λ₯Έ 값을 κ°€μ§€κΈ° λ•Œλ¬Έμ— staticκ³Ό ν•¨κ»˜ 쓰이지 μ•ŠλŠ”λ‹€.

5. Object 클래슀

μžλ°”μ˜ 클래슀λ₯Ό μ„ μ–Έν•  λ•Œ extends ν‚€μ›Œλ“œλ‘œ λ‹€λ₯Έ 클래슀λ₯Ό μƒμ†ν•˜μ§€ μ•ŠμœΌλ©΄ java.lang.Object 클래슀λ₯Ό μƒμ†ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ, μžλ°”μ˜ λͺ¨λ“  ν΄λž˜μŠ€λŠ” Object 클래슀의 μžμ‹μ΄κ±°λ‚˜ μžμ†μΈ ν΄λž˜μŠ€κ°€ λœλ‹€. μžλ°”μ˜ μ΅œμƒμœ„ λΆ€λͺ¨ ν΄λž˜μŠ€μ— ν•΄λ‹Ήν•˜λŠ” μ…ˆμ΄λ‹€.

➑️ Object ν΄λž˜μŠ€λŠ” ν•„λ“œκ°€ μ—†κ³  λ©”μ†Œλ“œλ‘œ κ΅¬μ„±λ˜μ–΄ μžˆλ‹€. 이 λ©”μ†Œλ“œλ“€μ€ λͺ¨λ“  ν΄λž˜μŠ€μ—μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.

λ©”μ†Œλ“œμ„€λͺ…
boolean equals(Object obj)두 객체가 같은지 λΉ„κ΅ν•œλ‹€.
String toString()객체의 λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•œλ‹€.
protected Object clone()객체λ₯Ό λ³΅μ‚¬ν•œλ‹€.
protected void finalize()κ°€λΉ„μ§€ μ»¬λ ‰μ…˜ 직전에 객체의 λ¦¬μ†ŒμŠ€λ₯Ό 정리할 λ•Œ ν˜ΈμΆœν•œλ‹€.
Class getClass()객체의 ν΄λž˜μŠ€ν˜•μ„ λ°˜ν™˜ν•œλ‹€.
int hashCode()객체의 μ½”λ“œκ°’μ„ λ°˜ν™˜ν•œλ‹€.
void notify()wait된 μŠ€λ ˆλ“œ 싀행을 μž¬κ°œν•  λ•Œ ν˜ΈμΆœν•œλ‹€.
void notifyAll()wait된 λͺ¨λ“  μŠ€λ ˆλ“œ 싀행을 μž¬κ°œν•  λ•Œ ν˜ΈμΆœν•œλ‹€.
void wait()μŠ€λ ˆλ“œλ₯Ό μΌμ‹œμ μœΌλ‘œ 쀑지할 λ•Œ ν˜ΈμΆœν•œλ‹€.
void wait(long timeout)μ£Όμ–΄μ§„ μ‹œκ°„λ§ŒνΌ μŠ€λ ˆλ“œλ₯Ό μΌμ‹œμ μœΌλ‘œ 쀑지할 λ•Œ ν˜ΈμΆœν•œλ‹€.
void wait(long timeout, int nanos)"
profile
κ·Έλž˜λ„ ν•΄μ•Όμ§€ μ–΄λ–‘ν•΄

0개의 λŒ“κΈ€