상속

현서·2025년 5월 22일
1

자바

목록 보기
9/32
post-thumbnail

1. 상속(Inheritance)

기존 클래스의 속성과 메서드를 새로운 클래스가 물려받아 재사용할 수 있게 해준다.

상속을 사용하면 공통된 코드를 중복 없이 여러 클래스에서 사용할 수 있어 코드의 재사용성과 확장성이 높아진다.

extends 키워드를 사용해 구현.

  • 기존 클래스 : 부모 클래스(슈퍼클래스)
  • 새로 정의한 클래스 : 자식 클래스(서브클래스) -> 부모의 기능을 그대로 사용 가능, 필요에 따라 기능을 확장하거나 재정의(오버라이딩) 가능
class 부모클래스 {
    // 공통 속성 및 동작 정의
}

class 자식클래스 extends 부모클래스 {
    // 부모의 기능을 상속받고 추가적인 기능 정의
}
package lesson03;

class Ex05_Animal {
    public void eat(){
        System.out.println("먹는다");
    }
}

class Ex05_Dog extends Ex05_Animal {
    public void bark(){
        System.out.println("멍멍 짖는다");
    }
}

public class Ex05_Main{
    public static void main(String[] args) {
        Ex05_Dog dog = new Ex05_Dog();
        dog.eat(); // 부모 것 쓸 수 있음
        dog.bark(); // 내 것도 쓸 수 있음
    }
}

1. 메서드 오버라이딩

자식 클래스는 부모 클래스의 메서드를 그대로 사용할 수도 있고, 필요에 따라 재정의(override) 할 수 있다.

class Animal {
    public void sound() {
        System.out.println("동물이 소리를 낸다.");
    }
}

class Cat extends Animal {
    @Override // 어노테이션. 쓰게 되면 컴파일할 때 오버라이드의 규칙에 맞는지 컴파일러에게 확인 요청
    public void sound() {
        System.out.println("야옹"); // 자식 것을 쓰게 된다.
    }
}

2. 자바에서의 상속 제약 사항

  • 한 클래스는 하나의 부모 클래스만 상속받을 수 있다.
class A {}
class B {}
class C extends A, B {} // ❌ 컴파일 에러
  • final 클래스는 상속할 수 없다.
final class Car {}
class SportsCar extends Car {} // ❌ 에러 발생
  • 생성자는 상속되지 않는다.
    생성자는 자식 클래스가 직접 정의해야 하며, 부모 생성자를 호출하려면 super()를 사용해야 한다.

3. super 키워드

  • 부모 클래스의 필드나 메서드에 접근할 때 사용한다.
  • 생성자 안에서 부모 생성자 호출에도 사용된다.
class Parent {
    public Parent(String msg) {
        System.out.println("부모 생성자: " + msg);
    }
}

class Child extends Parent {
    public Child() {
        super("안녕하세요");  // 부모 생성자 호출
        System.out.println("자식 생성자");
    }
}
package lesson03;

class Person{
    String name;
    public Person(String name){
        this.name = name;
    }
    public void greet(){
        System.out.println("안녕하세요, 저는 "+name+"입니다.");
    }
}

class Student extends Person{
    String school;
    public Student(String name, String school){
        super(name);
        this.school=school;
    }

    @Override
    public void greet() {
        super.greet();
        System.out.println("학교는 "+school+"입니다.");
    }
}

public class Ex07_Main {
    public static void main(String[] args) {
        Person person = new Person("김사과");
        person.greet();

        Student student = new Student("반하나", "코리아");
        student.greet();
    }
}

오른쪽 마우스 클릭! -> 생성 -> 메서드 재정의

재정의 할 메서드 선택 -> 확인
그러면 @Override가 뜬다!

2. final

자바에서 "변경할 수 없음"을 의미한다.

1. final 변수: 값 변경 불가 (상수)

선언과 동시에 값을 설정하거나, 생성자에서 한 번만 초기화 가능하며 관례상 대문자로 작성한다. (MAX_SIZE, PI 등)

final int MAX = 100;
MAX = 200; // ❌ 에러! 값을 바꿀 수 없음

2. final 메서드: 재정의(오버라이딩) 불가

보안성을 유지하며 중요한 로직이 변경되지 않도록 보호한다.

class Parent {
    public final void show() {
        System.out.println("부모 클래스 메서드");
    }
}

class Child extends Parent {
    // public void show() {} // ❌ 오류: final 메서드는 재정의할 수 없음
}

3. final 클래스: 상속 불가

클래스를 변경하거나 확장하지 못하도록 막고 싶을 때 사용한다.
String, Integer 같은 핵심 라이브러리 클래스들이 final로 선언되어 있다.

final class Animal {
    public void sound() {
        System.out.println("동물 소리");
    }
}

// class Dog extends Animal {} // ❌ 오류: final 클래스는 상속 불가

종합예제

package lesson03;

class Animal{
    String name;
    public Animal(String name){
        this.name = name;
    }
    public void eat(){
        System.out.println(name + "가 먹습니다.");
    }
    public final void sleep(){
        System.out.println(name + "는 조용히 잠듭니다.");
    }
    public void speak(){
        System.out.println(name + "가 소리를 냅니다.");
    }
}

class Dog extends Animal{
    public Dog(String name){
        super(name);
    }

    @Override
    public void speak() {
        System.out.println(name + "가 멍멍 짖습니다!");
    }
    public void bark(){
        System.out.println("멍멍!");
    }
    public void bark(String target){
        System.out.println(target + "를 보고 멍멍!");
    }
    public void bark(int times){
        for(int i = 0; i<times; i++){
            System.out.println("멍!");
        }
        System.out.println();
    }
}

public class Ex08_Main {
    public static void main(String[] args) {
        Dog rucy = new Dog("루시");
        rucy.eat();
        rucy.sleep();
        rucy.speak();
        rucy.bark();
        rucy.bark("택배 아저씨");
        rucy.bark(3);
    }
}

3. Object 클래스

모든 클래스의 최상위 부모 클래스(슈퍼클래스).

  • 자바에 존재하는 모든 클래스는 Object를 직접 또는 간접적으로 상속받는다.
  • 객체에 대한 기본적인 동작을 정의한 메서드들을 제공한다.

대표적인 메서드 : toString(), equals(), hashCode(), clone(), finalize() 등

class Person {
    // 실제로는 class Person extends Object 와 같음
}

Object 클래스가 제공하는 주요 메서드

toString() 객체를 문자열로 표현 (기본: 클래스이름@해시값)
equals(Object obj) 두 객체가 같은지를 비교 (기본: 주소 비교)
hashCode() 객체의 해시코드 반환
getClass() 클래스 정보를 담은 Class 객체 반환
clone() 객체 복제 (implements Cloneable 필요)
finalize() 가비지 컬렉션 전에 호출 (거의 사용되지 않음)

package lesson04;

import org.w3c.dom.ls.LSOutput;

class Person{
    String name;
    int age;

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "이름: " + name + ", 나이: " + age;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person other = (Person) obj;
        return this.name.equals(other.name) && this.age == other.age;
    }
}

public class Ex01_Main {
    public static void main(String[] args) {
        Person p1 = new Person("김사과",20);
        // System.out.println(p1.toString());
        Person p2 = new Person("반하나", 25);
        Person p3 = new Person("김사과",20);
        System.out.println(p1);// toString이 생략되어 있음.
        System.out.println(p2);// toString이 생략되어 있음.
        System.out.println(p3);// toString이 생략되어 있음.
        System.out.println(p1.equals(p2)); // 객체가 같은지 비교
        System.out.println(p1.equals(p3));
    }
}

4. 업캐스팅(Upcasting)

자식 클래스 객체를 부모 클래스 타입으로 참조하는 것.

업캐스팅을 사용하는 이유

  • 다형성(Polymorphism) 구현
  • 유지보수가 쉬운 코드 구조를 위해
  • 코드 재사용성과 확장성 향상

다운캐스팅과 비교
업캐스팅 자식 객체 → 부모 타입으로 참조 (자동)
다운캐스팅 부모 타입 참조 → 다시 자식 타입으로 형변환 (명시적)

package lesson04;

class Animal {
    public void sound(){
        System.out.println("동물이 소리를 냅니다.");
    }
}

class Dog extends Animal{
    @Override
    public void sound() {
        System.out.println("멍멍!");
    }

    public void wagTail(){
        System.out.println("꼬리를 흔듭니다.");
    }
}

public class Ex02_Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
        dog.wagTail();
        Animal animal = dog; // 업캐스팅 / 객체의 주소를 넘겨줌. 형태는 부모형태.
        animal.sound();
        // animal.wagTail();
        Dog dog2 =(Dog) animal; // 다운캐스팅
        dog2.sound();
        dog2.wagTail();
    }
}

5. 이종모음(heterogeneous collection)

서로 다른 타입의 객체들을 하나의 컬렉션에 담아 처리하는 구조.

instanceof란?

객체가 특정 클래스의 인스턴스인지 확인하는 연산자.
객체가 어떤 클래스 또는 그 하위 타입으로부터 생성되었는지를 판별할 때 사용되며, 결과는 true 또는 false를 반환한다.

객체 instanceof 클래스이름
  • 결과는 boolean 타입
  • 객체가 해당 클래스 또는 그 자식 클래스의 인스턴스이면 true, 아니면 false
  • 주로 다운캐스팅하기 전에 안전하게 타입 확인할 때 사용
  • 자바 16부터는 instanceof와 다운캐스팅을 한 줄로 작성할 수 있게 패턴 매칭이 도입
package lesson04;

class Book {
    String title;
    public Book(String title){
        this.title=title;
    }
    public void read(){
        System.out.println("책 \"" + title + "\"을 읽습니다.");
    }
}

public class EX03_Main {
    public static void main(String[] args) {
        /*
        Object[] items = new Object[3];
        items[0] = "안녕하세요";
        items[1] = 100;
        items[2] = new Book("자바의 정석");

        for(Object obj : items){
            if(obj instanceof String){
                System.out.println("문자열: " + obj);
            }else if(obj instanceof Integer){
                System.out.println("정수: " + obj);
            }else if(obj instanceof Book){
                Book book = (Book) obj;
                book.read();
            }
         */
        Object[] items = new Object[3];

        items[0] = "안녕하세요";            // String
        items[1] = 100;                   // Integer (오토박싱)
        items[2] = new Book("자바의 정석"); // 사용자 정의 클래스

        // 배열 순회하며 타입 확인 및 처리
        for (Object obj : items) {
            if (obj instanceof String str) {
                System.out.println("문자열: " + str);
            } else if (obj instanceof Integer num) {
                System.out.println("정수: " + num);
            } else if (obj instanceof Book book) {
                book.read();  // 자동으로 Book 타입으로 다운캐스팅됨
            }
        }
    }
}
profile
The light shines in the darkness.

0개의 댓글