6 minute read




상속(Inheritance)

상속의 개념

[ 상속이란 ]

상속이란, 기존에 정의된 클래스(부모 클래스, 상위 클래스)의 속성과 메서드를 새로운 클래스(자식 클래스, 하위 클래스)가 물려받아 재사용할 수 있도록 하는 개념

[ 상속을 사용하는 이유 ]
• 소프트웨어를 재사용(reuse)하는 방법
• general class definition -> specialized class를 간단하고 효과적으로 정의
• 기존내용을 변경해 클래스를 정의하여 필요한 정보만 추가

상속과 객체 간 관계

[ Inter-class Relationships ]
IsA relation(상속 관계)

• 하위 타입(subtype)을 정의함
• 주로 공통적인 속성과 기능을 재사용하고자 할 때 사용
• A(자식클래스)가 B(부모클래스)의 일종이다 라는 의미
• Java에서 extends 키워드를 사용함

// 자동차는 탈것(Vehicle)의 일종이다
class Automobile extends Vehicle { ... }
// 상속관계(isA)를 예로 설명한 도형 클래스 계층도

                 Shape
               /       \
         2DShape       3DShape
         /   |   \         |   \
     Oval Rectangle Triangle  Sphere Cube
      |       |       |
    Circle  Square  EquilateralTriangle
                         \
                      IsoscelesTriangle

       Parallelogram
              |
           Diamond

HasA relation(포함 관계)
• 복합 객체(composite)를 정의함
• 객체를 하위 구성요소로 포함함
• 코드에서는 클래스 내부에 다른 객체 타입을 필드로 선언함으로써 표현
• 이런 관계는 클래스 내부에 부품처럼 다른 객체를 조립해서 쓰는 구조
• A가 B를 갖고 있다는 의미

// 자동차는 바퀴를 갖고 있다" → 자동차 클래스 안에 Wheel 객체를 포함
class Automobile ... {
    Color shade;
    Wheel wheels[4];
    ...
}


[ Object 클래스와 메서드들]
정의

Object 클래스
클래스 계층 구조의 최상위 클래스로, 모든 클래스는 Object의 메소드를 자동으로 상속
클래스 계층의 뿌리 (※ 객체가 아닌 Object라는 이름)
java.lang 패키지에 정의되어 있음
모든 클래스의 슈퍼클래스 (기본 명세 제공)

clone()
equals(Object)          // 두 객체가 같은지 비교
finalize()  
getClass()
hashCode()              // 객체의 해시값 반환 (HashMap, HashSet에 중요)
notify()                // 멀티스레드 간의 대기/알림 기능
notifyAll()
toString()              // 객체를 출력할 때 문자열로 표현
wait([long][, nanosec]) // 멀티스레드 간의 대기/알림 기능

참고 java SE document를 구글에 검색해서 → Oracle의 공식 Java API 문서에 들어감
java.base 모듈 → java.lang 패키지 → Object 클래스를 확인
클래스 계층과 함께 Object 클래스의 메소드 요약(설명 포함)을 볼 수 있음

[ 요약 ]
• 상위 클래스의 변수/메소드를 상속-> 재활용 한다
(e.g., student: getName() == super.getName())
• 모든 (학생/교수/직원)을 한 가지의 종류(Person)으로 다 룰/저장할 수 있다: 다형성(polymorphism)
• 상위 클래스의 생성자를 호출/실행할 수 있다
(e.g., super(…));
• 상위 클래스의 메쏘드를 overriding 하기도 한다
(e.g., student: info() == Student.info() =! Person.info())
• 상위 클래스의 overridden 메쏘드를 직접 호출할 수 있다
(e.g., super.info())




메소드 오버라이딩

overriding, 대체

[ 정의 ]

클래스 상속 관계에서 반환자료형, 메쏘드 이름, 인자형과 인자수가 같을 때 파생 클래스의 메쏘드를 사용하는 것

[ 오버로딩 vs 오버라이딩 ]
overriding(대체) <-> overloading(중복, 한 클래스 내에서)

[ 오버라이딩의 내부 실행 과정 ]

student.getName()

메쏘드 호출 > 현클래스에서 메쏘드 탐색 > 없으면 직상위 클래스 탐색 > 없으면 차상위 > 결국 못찾으면 오류(compile error)

[ 예시 ]

People - Student - MaleStudent hierarchy:
• People → writeOutput() 출력: “a”
• Student2 → writeOutput() 출력: “b”
• MaleStudent → writeOutput() 출력: “c”

참고 오버라이딩된 메서드는 가장 하위 클래스의 것을 우선 실행함

People  Student2  MaleStudent
클래스 멤버변수 접근제어자 자식클래스 접근
People penName private
People name protected
Student2 studentYear private
MaleStudent doArmy private
class People {
    private String penName;

    People() { ... }
    People(String name) { ... }

    public String changeName(String name) {
        this.name = name;
    }

    public void writeOutput() {
        System.out.println("내 이름: " + name);
    }

    protected String name;
}
// name은 protected로 선언되어, 하위 클래스(Student2, MaleStudent)에서 사용 가능
// penName은 private이라 자식 클래스에서 접근 불가
class Student2 extends People {
    Student2() { ... }
    Student2(String name, ...) { ... }

    public void reset(String name, int year) {
        changeName(name);
        studentYear = year;
    }

    public void writeOutput() {
        System.out.println("제 이름: " + name);
    }

    private int studentYear;
}
// changeName()을 호출해 People 클래스의 name 필드를 설정
// studentYear는 private이므로 MaleStudent에서 직접 접근 불가
class MaleStudent extends Student2 {
    MaleStudent() { ... }
    MaleStudent(String name, ...) { ... }

    public void writeOutput() {
        System.out.println("제 이름: " + name);
        System.out.println("학년: " + studentYear);
        System.out.println("병역필: " + doArmy);
    }

    private boolean doArmy; // dutyOfArmy
}
// name은 protected → 접근 가능
// studentYear는 private → 직접 접근 불가 (오류 발생)
// doArmy는 자신의 클래스에 선언된 private → 내부에서는 접근 가능




다형성 (feat. overriding)

다형성이란

[ 클래스 상속에 의한 계층구조에서 method의 다형성 ]

• 어떤 A라는 객체가 동작하는데 같은 상황임에도 불구하고 다른 모습을 갖거나, 다른 동작을 하는 (것처럼 보이는) 현상
• 상속 관계에서 overriding으로 나타나는 현상/특성

[ 예시 - animal farm choir ]

class Animal {
    private int nLegs = 4;
    public void talk() {
        System.out.println(조용~);
    }
}

class Dog extends Animal {
    public void talk() { System.out.println(멍멍!); }
}

class Pig extends Animal {
    public void talk() { System.out.println(꿀꿀!); }
}

class Snake extends Animal {
    private int legs = 0;
}

public class AnimalFarmChorus{
    public static void main(Stirng[] args){
        Dog aDog = new Dog();
        Pig aPig = new Pig();

        Animal animal;

        // polymorphism
        // 같아 보이는 animal 인데 talk()를 자동 선택해줌
        animal = aDog;  // promotion: dog > animal
        animal.talk();

        animal = aPig;
        animal.talk();

        // without polymorphism
        if(animal == aDog) aDog.talk();
        else if(animal == aPig) aPig.talk();
    }
}

// result: 멍멍 > 꿀꿀

다형성을 만드는 두가지 방법!

[ 메서드 오버로딩 (Method Overloading) ]

• 같은 이름의 메서드/생성자를 매개변수만 다르게 정의하는 것(반환형만 다르면 안됨)
컴파일 시점(polymorphism at compile time)에 어떤 메서드가 호출될지 결정됨

[ 메서드 오버라이딩 (Method Overriding) ]

• 상속받은 메서드를 하위 클래스에서 재정의하여 다른 동작을 하게 함
실행 시점(polymorphism at runtime)에 어떤 메서드가 호출될지 결정됨

|구분|오버로딩|오버라이딩| |—|—|—| |다형성 종류|컴파일 타입 다형성|런타임 다형성| |대상|같은 클래스, 상속 관계|상속 관계에서만| |조건|이름은 같고, 매개변수가 다름|이름, 매개변수, 반환형 모두 동일| |결정시점|컴파일|실행| |@Overrid 필요|필요없음|권장|


다형성의 실현

상속관계에서 메쏘드 overriding으로 다형성 실현
• 하나의 이름/(인터페이스)에 서로 다른 구현
• 수퍼 클래스의 메쏘드 draw(), talk()를 여러 서브 클래스에서 각각 목적에 맞게/다르게 (재)구현
• Shape의 draw() 메소드를 Line, Rect, Circle에서‘대체’하여 다르게 구현

// super class - Shape
class Shape{
    public void draW(){
        System.out.println("Shape");
    }
}

// super class - Line
class Line extends Shape{
    public void draW(){
        System.out.println("Line");
    }
}

// super class - Rect
class Rect{
    public void draW(){
        System.out.println("Rect");
    }
}

// super class - Circle
class Circle{
    public void draW(){
        System.out.println("Circle");
    }
}



캐스팅과 기타 문법(static, fianl)

[ Casting ]

종류 내용
Promotion (승급) • subclass 객체를 superclass 객체로 치환
• Animal animal = aDog;
Demotion (강등) • superclass 객체를 subclass 객체로 치환
• casting: 강제적 형변환이 필요하다 Dog bDog = (Dog) animal;
• 컴파일러 타당/통과: animal이 위처럼 원래 Dog 객체가 아니었다면 실행할 때 오류가 발생

[ instanceof 연산자 ]

💡 instanceof 연산자
참조(변수)가 가리키는 객체의 유형(class) 식별
• 형식: 객체_참조 instanceof 클래스명
• 연산의 결과: true, false

Person p = new Professor();
// new Professor() 객체는 Professor 타입이면서, 동시에 Employee 타입이기도 하고, Person 타입이기도 함

If (p instanceof Person)        //true
If (p instanceof Student)       // false. Student를 상속받지 않았다
If (p instanceof Employee)      // true 
If (p instanceof Professor)     // true

If ("java" instanceof String) // true

If (3 instanceof int) // 문법 오류. instanceof는 참조 자료형에만 사용


[ final and static ]

final
 ├─ 변수        고정 (변경 )
 ├─ 메서드     자식 클래스에서 오버라이딩 
 └─ 클래스     다른 클래스가 상속 

//클래스에 final이 붙으면 상속자체가 X > 오버라이딩 X

static final

오버라이드(재정의) 불가능한 클래스 변수
• static final로 선언된 변수는 변경할 수 없는 상수
• 클래스 차원에서 고정된 값

static final float CmPerInch = 2.54;

본질적으로 상수인 변수들 (constant)
• final static 조합은 상수 선언에 자주 사용
• 공용(static)이고, 변경 불가능(final)함

public final static float C = 2.9989E+10f;
public final static int SCREEN_WIDTH = 640;

주의 오버라이드 금지 예시

class A {
    final int a;
}

class B extends A {
    float a;   // ❌ 오류! final 변수는 하위 클래스에서 재정의 불가
}
final class Dinosaur { ... }

void with(final Animal a) {
    // a = new Animal(); ← ❌ final 파라미터는 값 변경 불가
    a.talk();            // ✅ 사용은 가능
}

// final class: 상속 금지
// final parameter: 메서드 매개변수 값 변경 불가

Tags:

Categories:

Updated: