SEB_BE_43 / 22.12.30 회고

rse·2023년 1월 5일
0

코드스테이츠_BE_43

목록 보기
10/65

오늘의 핵심

  • 다형성
  • 추상화

다형성

다형성은 같은 참조 변수에서 다양한 결과가 나오는 것.

지금 붕어빵 틀은 Friend 에서 가져오고 속은 GirlFriend로 채운셈이다.
이걸 객체 타입과 참조변수 타입의 불일치라고 한다.


반대로는 불가능.

참조변수의 타입 전환

참조변수의 타입을 전환하는 것도 가능하다

타입 변환을 위해서는 다음의 세 가지 조건을 충족해야한다.

  1. 서로 상속관계에 있는 상위 클래스 - 하위 클래스 사이에만 타입 변환이 가능합니다.

  2. 하위 클래스 타입에서 상위 클래스 타입으로의 타입 변환(업캐스팅)은 형변환 연산자(괄호)를 생략할 수 있습니다.

  3. 반대로 상위 클래스에서 하위 클래스 타입으로 변환(다운캐스팅)은 형변환 연산자(괄호)를 반드시 명시해야합니다.

  • 또한, 다운 캐스팅은 업 캐스팅이 되어 있는 참조변수에 한해서만 가능합니다.

instanceof

instanceof는 스팅이 가능한 지 여부를 boolean 타입으로 확인할 수 있는 문법이다.

참조_변수 instanceof 타입


추상화

의미

공통성과 본질을 모아 추출하는 것
상속과 다른 점 : 기존 클래스들의 공통적인 요소들을 뽑아서 상위 클래스를 만들어 내는 것

abstract 제어자

abstract class AbstractExample { // 추상 메서드가 최소 하나 이상 포함돼있는 추상 클래스
	abstract void start(); // 메서드 바디가 없는 추상메서드
}

abstract의 가장 핵심적인 개념 '미완성'에 있다.

추상 클래스를 사용하면 상속을 받는 하위 클래스에서 오버라이딩을 통해 각각 상황에 맞는 메서드 구현이 가능하다는 장점이 있다.

두 번째로, 추상 클래스는 자바 객체지향 프로그래밍의 마지막 기둥인 추상화를 구현하는데 핵심적인 역할을 수행한다.

추상화를 한마디로 정리하면 “객체의 공통적인 속성과 기능을 추출하여 정의하는 것”이라 정리할 수 있다

추상 메서드는 존재 할 수도 있고, 존재하지 않을 수도 있음.
하지만 존재하지 않는다면 굳이 추상화 해줄 필요 없다고 함.

추상 메서드가 존재 할 경우 상속 받은 하위 클래스들은 반드시 구현해야 함. 자기 자신에 맞게 오버라이딩.

추상 메서드의 경우 바디가 없다.

abstract void start();

이제 이걸 하위 클래스에서 오버라이딩하여 구현해주면 된다.

final 키워드

클래스 = 변경 또는 확장 불가능한 클래스, 상속 불가
메서드 = 오버라이딩 불가
변수 = 값 변경이 불가한 상수

인터페이스

추상 메서드의 집합
기본적으로 추상 메서드와 상수만을 멤버로 가질 수 있다.

public interface InterfaceEx {
    public static final int rock =  1; // 인터페이스 인스턴스 변수 정의
    final int scissors = 2; // public static 생략
    static int paper = 3; // public & final 생략

    public abstract String getPlayingNum();
		void call() //public abstract 생략 
}

인터페이스는 이런 식으로 쓸 수 있다.

또한 인터페이스는 다중 구현이 가능하다.

public class InterfaceExample {
    public static void main(String[] args) {
        User user = new User(); // User 클래스 객체 생성
        user.callProvider(new Provider()); // Provider 객체 생성 후에 매개변수로 전달
    }
}

class User { // User 클래스
    public void callProvider(Provider provider) { // Provider 객체를 매개변수로 받는 callProvider 메서드
        provider.call();
    }
}

class Provider { //Provider 클래스
    public void call() {
        System.out.println("무야호~");
    }
}

이런 코드가 있을 때 만약 Provider 클래스를 다른 클래스로 변경해야 한다면?

public class InterfaceExample {
    public static void main(String[] args) {
        User user = new User(); // User 클래스 객체 생성
        user.callProvider(new Provider2()); // Provider객체 생성 후에 매개변수로 전달
    }
}

class User { // User 클래스
    public void callProvider(Provider2 provider) { // Provider 객체를 매개변수로 받는 callProvider 메서드
        provider.call();
    }
}

class Provider2 { //Provider 클래스
    public void call() {
        System.out.println("야호~");
    }
}

이런 식으로 많이 변경해줘야겠지.
하지만 이게 지금처럼 짧은 코드가 아니라 긴 코드였다면?
몇 줄 수정이 아니라 엄청난 수정을 해야할 것이다.

이럴 경우를 대비해서 인터페이스를 쓴다.

interface Cover { // 인터페이스 정의
    public abstract void call();
}

public class Interface4 {
    public static void main(String[] args) {
        User user = new User();
//        Provider provider = new Provider();
//        user.callProvider(new Provider());
        user.callProvider(new Provider2());
    }
}

class User {
    public void callProvider(Cover cover) { // 매개변수의 다형성 활용
        cover.call();
    }
}

class Provider implements Cover {
    public void call() {
        System.out.println("무야호~");
    }
}

class Provider2 implements Cover {
    public void call() {
        System.out.println("야호~");
    }
}

이제 Provider에 문제가 생기더라도 User 코드는 수정해주지 않아도 된다.

profile
기록을 합시다

0개의 댓글