2020년 10월 22일

업데이트:


다형성

객체지향 프로그래밍 3대 특징 중 하나로 ‘여러 개의 형태를 갖는다’는 의미이다. 하나의 행동으로 여러 가지 일을 수행하는 개념이며, 상속을 이용한 기술로 부모 클래스 타입 참조변수 하나로 상속 관계에 있는여러 타입의 자식 객체를 참조할 수 있는 기술이다.


업 캐스팅(Up Casting)

상속 관계에 있는 부모, 자식 클래스 간에 부모타입의 참조형 변수가 모든 자식 타입 객체의 주소를 참조할 수 있다.


다운 캐스팅(Down Casting)

자식 객체의 주소를 받은 부모 참조형 변수를 가지고 자식의 멤버를 참조해야 할 경우, 부모 클래스 타입의 참조형 변수를 자식 클래스 타입으로 형변환 하는 것. 자동 처리되지 않기 때문에 반드시 자식 타입을 명시하여 형변환


바인딩

정적 바인딩

프로그램이 실행되기 전 컴파일 단계에서 메소드와 메소드 호출부를 연결해준다.


동적 바인딩

컴파일 시 정적 바인딩 된 메소드를 실행할 당시의 객체 타입을 기준으로 바인딩 된다.


// Animal.java

public class Animal {
    public void eat() {
        System.out.println("영양분 섭취한다.");
    }

    public void breath() {
        System.out.println("숨을 쉰다.");
    }
}


// Fish.java

public class Fish extends Animal {
    private int fin;

    @Override
    public void eat() {
        System.out.println("물고기는 밥을 뻐끔뻐끔 먹는다.");
    }

    @Override
    public void breath() {
        System.out.println("물고기는 아가미로 숨을 쉰다.");
    }

    public void swim() {
        System.out.println("물고기는 헤엄을 칠 수 있다.");
    }
}


// Person.java

public class Person extends Animal {
    private String name;

    public Person() {
        super(); // 상속 관계에 있는 부모 객체를 자식 객체 생성 시 추가해야 하므로 자식 생성자 첫 번째 줄에 super() 생성자 작성
        // 미작성 시 컴파일러가 자동으로 추가한다.
    }

    @Override
    public void eat() {
        System.out.println("사람은 식기를 이용해서 음식을 먹는다.");
    }

    @Override
    public void breath() {
        System.out.println("사람은 코와 입으로 숨을 쉰다.");
    }

    public void studyJava() {
        System.out.println("사람은 누구나 자바를 공부할 수 있다.");
    }
}


// Snake.java

public class Snake extends Animal {
    private String poison;

    @Override
    public void eat() {
        System.out.println("뱀은 통째로 삼킨다.");
    }

    @Override
    public void breath() {
        System.out.println("뱀은 피부 호흡을 한다.");
    }

    public void lock() {
        System.out.println("뱀은 먹이를 조른다.");
    }
}


// PolyService.java

public class PolyService {
    public void example1() { 
        Animal a = new Animal();

        // 업캐스팅 : 참조 변수의 타입이 부모 타입으로 변경되는것
        // -> 부모 타입의 참조 변수로 자식 객체 참조
        Animal person = new Person();
        
        // person.studyJava(); // 자식 객체의 고유 기능을 참조할 수 없음
        a.eat();
        person.eat();
        // Person 객체 내부에 존재하는 Animal 객체의 eat() 호출
        // --> 정적 바인딩


        // Person(Animal)이 참조하고 있는 객체의 eat()를 호출하면
        // 내부에 존재하는 Animal 객체의 eat()가 아닌
        // 오버라이딩 된 Person의 eat()를 호출함
        //  ---> 동적 바인딩

        Animal[] arr = new Animal[4];
        arr[0] = new Animal();
        arr[1] = new Person();
        arr[2] = new Fish();
        arr[3] = new Snake();

        for(int  i = 0; i < arr.length; i++){
            arr[i].breath();
        }
        // arr[0], [1], [2] 인덱스 요소가 참조하고 있는
        // 자식 객체들이 부모인 Animal로부터 상속받은
        // breath() 메소드를 오버라이딩하였기 때문에
        // 컴파일 전에는 부모의 breath()로 바인딩 되어 있다가(정적  바인딩)
        // 실행 중에는 각자 오버라이딩 된 breath()가 실행됨 (동적 바인딩)


        // 다운 캐스팅
        // 부모 참조 변수 = 자식 객체
        // 참조변수가 부모 -> 자식으로 변함으로써
        // 자식 객체를 온전히  참조할 수 있게 된다.

        ((Person) arr[1]).studyJava();
        ((Fish) arr[2]).swim();
        ((Snake) arr[3]).lock();
    }
}



instanceof 연산자

현재 참조형 변수가 어떤 클래스 형의 객체 주소를 참조하고 있는지 확인할 때 사용한다. 클래스 타입이 맞으면 true, 맞지 않으면 false를 반환한다.

// PolyService.java

for(int i = 0; i < arr.length; i++){
    if(arr[i] instanceof Person){
        ((Person) arr[i]).studyJava();
    } else if (arr[i] instanceof Fish){
        ((Fish) arr[i]).swin();
    } else if(arr[i] instanceof Snake) {
        ((Snake) arr[i]).lock();
    } else {
        System.out.println("그냥 Animal 객체입니다.");
    }
}



추상 클래스

몸체 없는 메소드를 포함한 클래스며 추상 클래스일 경우 클래스 선언부에 abstract 키워드를 사용한다.


추상 메소드

몸체 없는 메소드이며 추상 메소드의 선언부에 abstract 키워드를 사용한다. 상속 시 반드시 구현해야 하는, 오버라이딩이 강제화되는 메소드이다.


추상 클래스 특징

  1. 미완성 된 클래스로 자체적으로 객체 생성이 불가능하다. → 반드시 상속하여 객체를 생성해야 한다.
  2. abstract 메소드가 포함된 클래스는 반드시 abstract 클래스 abstract 메소드가 없어도 abstract 클래스 선언이 가능하다.
  3. 클래스 내에 일반 변수, 메소드를 포함할 수 있다.
  4. 객체 생성은 안되지만 참조형 변수 타입으로는 사용이 가능하다.

장점

  • 일관된 인터페이스를 제공한다.
  • 꼭 필요한 기능을 강제화(공통적이나 자식 클래스에서 특수화 되는 기능) 한다.

인터페이스

인터페이스_위키백과

상수형 필드와 추상 메소드만을 작성할 수 있는 추상 클래스의 변형체이며, 메소드의 통일성을 부여하기 위해 추상 메소드만 따로 모아놓은 것으로 상속 시 인터페이스 내에 정의된 모든 추상 메소드를 구현해야 한다.

[접근제한자] interface 인터페이스명 {
    // 상수도 멤버로 포함 가능
    public static final 자료형 변수명 = 초기값;

    // 추상 메소드만 선언 가능
    [public abstract] 반환자료형 메소드명([자료형 매개변수]);
    //public abstact가 생략되기 때문에 오버라이딩 시 반드시 public 표기
}


특징

  1. 모든 인터페이스의 메소드는 묵시적으로 public이고 abstract이다.
  2. 변수는 묵시적으로 public static final 따라서 인터페이스 변수의 값 변경 시도 시 컴파일 에러가 발생한다.
  3. 객체 생성은 불가하나 참조형 변수로는 가능하다.

장점

  • 상위 타입 역할로 다형성을 지원하여 연결한다.
  • 해당 객체가 다양한 기능 제공 시에도 인터페이스에 해당하는 기능만을 사용하게 제한한다.
  • 공통 기능 상의 일관성을 제공한다.
  • 공동 작업을 위한 인터페이스를 제공한다.

태그:

카테고리:

업데이트:

댓글남기기