본문 바로가기
728x90

230724 객체지향 프로그래밍 - 다형성, 추상 클래스

🌍TISTORY

  • 다형성
  • 추상클래스
  • 추가) 바인딩 - 동적 바인딩, 정적 바인딩

다형성


다형성의 모습

다형성 0다형성 0

`public class Person {
    String name;
    int age;
    Person() {}
    Person(String name) {
        this.name = name;
    }
    public void eat () {
        System.out.println("음식을 먹는다.");
    }
}
public class Student extends Person {
    String major;
    public void study() {
        System.out.println("공부를 한다.");
    }
}
  • 다형성이란 多形을 가질 수 있는 성질
  • 상속관계에 있을 때 조상 클래스의 타입으로 자식 클래스 객체를 참조할 수 있다

다형성 1다형성 1
다형성 2다형성 2

메모리 상의 모습

= new Student

다형성 3다형성 3

참조변수의 형 변환

다형성 4다형성 4

  • 자손타입 → 조상타입 (묵시적 형 변환)
  • 형 변환 생략 가능
Student st = new Student();
Person p = st;

다형성 5다형성 5

Person p = new Student();
Student st = (Student) p;

참조변수의 형 변환

다형성 6다형성 6

Person p = new Person();
Student st = (Student) p;

다형성 7다형성 7
다형성 8다형성 8

instanceof 연산자

다형성 9다형성 9

  • 참조변수가 참조하고 있는 인스턴스의 타입을 확인하기 위해 사용
  • 결과를 boolean으로 반환
  • true가 반환되면 해당 타입으로 형 변환 가능
Person perseon = new Person();

if (person instanceof Student) {
    Student student = (Studnet) person;
    student.study();
}

참조 변수와 인스턴스 멤버의 관계

class Parent {
    String x = "parent";
    public Stirng method() {
        return "parent method!!!!";
    }
}

class Child extends Parne {
    String x = "child";

    @Override
    public String method() {
        return "child method!!!!";
    }
}
public class BindingTest {
    public static void main(String[] args) {
        Parent p = new Child();
        Child c = new Child();

        System.out.println(p.x);
        System.out.println(p.method());

        System.out.println(c.x);
        System.out.println(c.method());
    }
}
  • 상속관계에서 멤버 변수가 중복되면 참조 타입에 따라 연결이 달라짐
  • 메서드가 중복될 때 무조건 자식 클래스의 메서드가 호출됨
  • static 메서드는 참조변수 타입의 영향을 받기 때문에 이를 방지하고자 클래스 이름으로 메서드 호출
  • 다형성의 활용 - 다른 타입의 객체를 다루는 배열

다형성 10다형성 10
다형성 11다형성 11
다형성 12다형성 12

다형성의 활용 - 매개변수의 다형성

  • 사람의 정보를 출력하려면
    public String info(Teacher t) { }
    public String info(Student st) { }
    public String info (Person p) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }

동적 바인딩… 공부하기

추상클래스 (abstract class)


추상클래스

상속을 강제하기 위한 것

메소드의 시그니처만 정의해 놓고 그 메소드의 실제 동작 방법은 이 메소드를 상속받은 하위 클래스의 책임으로 위임한다.

다형성 13다형성 13

추상 클래스 정의

다형성 14다형성 14

public class KFoodChef {
    String name;
    int age;
    String speciality;

    public void eat(){
        System.out.println("음식을 먹는다.");
    }

    public void cook() {
        System.out.println("한식을 요리한다.");
    }
}

public class JFoodChef {
    String name;
    int age;
    String speciality;

    public void eat() {
        System.out.println("음식을 먹는다.");
    }

    public void cook() {
        System.out.println("일식을 요리한다.");
    }
}

추상 클래스 정의

다형성 15다형성 15

public class Chef {
    String name;
    int age;
    String speciality;
    public void eat() {
        System.out.println("음식을 먹는다.");
    }
    public void cook() {
        System.out.println("전공에 맞는 요리한다.");
    }
}

public class KFoodChef extends Chef{
@Override
    public void cook() {
        System.out.println(“한식을 요리한다.");
    }
}

public class JFoodChef extends Chef{
 @Override
    public void cook() {
        System.out.println("일식을 요리한다.");
    }
}
public class ChefTest {
    public static void main(String[] args) {
        Chef[] chefs = new Chef[2];
        chefs[0] = new KFoodChef();
        chefs[1] = new JFoodChef();
        for(Chef chef : chefs) {
            chef.eat();
            chef.cook();
        }
    }
}
  • 한식요리사, 일식요리사 모두 cook 메서드를 가지고 있음.
  • 조상 클래스 Chef에 선언하고 각 자손 클래스에서 override 예정
  • 사용되지 않는 Chef 클래스에 cook() 메서드가 필요한가?
    → 요리사라는 객체를 만들 때 전공을 무조건 선택하게 한다면 **= 자손 클래스에서 무조건 재정의** Chef (cook()) 메서드는 필요 없지 않나?
public class Chef {
    String name;
    int age;
    String speiciality;

    public void eat() {
        System.out.println("음식을 먹는다.");
    }

    public void cook() {
        System.out.println("전공에 맞는 요리한다.");
    }
}
for (Chef chef: chefs) {
    chef.eat();
    if (chef instanceof KFoodChef) {
        KFoodChef k = (KFoodChef) chef;
        k.cook();
    } else if (chef instanceof JFoodChef) {
        ((JFoodChef) chef).cook();
    }
}

다형성 16다형성 16

  • cook() 메서드는 자손 클래스에서 반드시 재정의해서 사용되기 때문에 조상의 구현이 무의미
  • 하지만? “전공에 맞는 요리를 한다” 를 삭제했는데,
    모두가 cook 메서드를 가지고 있지만 cook 메서드에 대한 강제성이 없음! cook 메서드가 없는 클래스가 존재할 수도 있음
  • 메서드의 선언부만 남기고 구현부는 ;(세미콜론)으로 대체 ::: 미완성 method
    미완성 method 자식 클래스에서 무조건 재정의해야 한다는 것을 의미
    → 자식 클래스에서 재정의하지 않으면 빨간 줄 나옴~
    → Chef 클래스도 미완성 클래스가 됨
  • 구현부가 없으므로 abstract 키워드를 메서드 선언부에 추가
  • 객체를 생성할 수 없는 클래스라는 의미로 클래스 선언부에 abstract를 추가
public abstract class Chef {
    String name;
    int age;
    String speciality;

    public void eat() {
        System.out.println("음식을 먹는다.");
    }

    public abstract void cook();
}

추상 클래스 특징

  • abstract 클래스는 상속 전용의 클래스 → 인스턴스 생성 불가
  • 클래스에 구현부가 없는 메서드가 있으므로 객체를 생성할 수 없음
  • 상위 클래스 타입으로 자식을 참조할 수는 없음
    //생성할 수 없음
    Chef chef1 = new Chef();
    Chef chef2 = new KFoodChef();
  • 조상 클래스에서 상속받은 abstract 메서드를 재정의하지 않은 경우
    클래스 내부에 abstract 메서드가 있으므로 자식 클래스는 abstract 클래스가 되어야 함

∴ 추상 클래스 사용하는 이유?

  • abstract 클래스는 구현의 강제를 통해 프로그램의 안정성 향상
  • 부모가 구현하고 싶은 내용이 없다고 해서 구현하지 않는다면, 동적 바인딩에 의해 자식의 오버라이딩된 함수가 실행되지 않음!!
  • 아무것도 작성하지 않은 {} 를 만들어 놓으면 자식이 구현하든, 하지 않든 상관없음
  • abstract로 만들어 두면 무조건 구현해야 하는 의무를 부여함

### 정리

추상클래스는 미완성의 설계도: 인스턴스를 생성할 수 없음

인스턴스를 생성할 때 미완성된 부분을 만들어 주면 됨!

익명 클래스 문법을 이용해서 1회 한정으로 구현하고 인스턴스를 만들 수 있게 도와준다

Chef c2 = new Chef() {
    public void cook () {
        System.out.println("아무요리나다해버림ㅎㅎ");
    }
}

Binding 바인딩


바인딩이란?

  • Association of method call to the method body: 메서드 호출과 메서드 본문의 연결
  • 컴퓨터 프로그래밍에서 각종 값들이 확정되어 더이상 변경할 수 없는 구속(bind) 상태가 되는 것
  • 프로그램 내에서 식별자(identifier)가 그 대상인 메모리 주소, 데이터형 또는 실제 값으로 배정되는 것

Static Binding 정적 바인딩

  • 컴파일링 또는 링크 시에 확정되는 바인딩을 의미
  • 실행 이전에 값이 확정되면 → 정적 바인딩
  • static private final method: override 불가능하며 compile 시점에 타입이 결정된다.

Dynamic Binding 동적 바인딩

  • 프로그램이 실행되는 과정에서 바인딩되는 것을 의미
  • method overriding: 부모와 자식 클래스에 모두 동일한 메서드가 존재하고 오직 실행 시점에 타입이 결정되어 해당 타입의 method가 실행됨
728x90
네이버밴드네이버블로그핀터레스트텔레그램링크드인포켓레딧이메일

개발자 연습생