다형성 & 추상화&인터페이스

InSeok·2022년 7월 13일
0

TIL

목록 보기
13/51

목차


  1. 다형성
  2. 참조변수의 타입 변환
  3. instanceof 연산자
  4. 추상화
  5. abstract제어자
  6. final 키워드
  7. 인터페이스

배운 내용


다형성

정의

  • 하나의 객체가 여러 가지 형태를 가질 수 있는 성질
  • 상위 클래스 타입의 참조변수를 통해서 하위 클래스의 객체를 참조할 수 있도록 허용한 것
    • 그 반대는 허용되지 않는다. 즉, 하위 클래스 타입의 참조변수를 통해 상위 클래스의 객체를 참조하는 것은 불가능
    • 참조 변수의 타입의 멤버가 실제 인스턴스의 멤버 수보다 작은 것은 실제 사용할 수 있는 기능을 줄이는 것이기에 허용되지만, 그 반대의 경우는 참조하고 있는 인스턴스에 실제로 구현된 기능이 없어 사용이 불가하기 때문
// BoyFriend, GirFriend < Friend 상속관계
				Friend friend = new Friend(); // 객체 타입과 참조변수 타입의 일치
        BoyFriend boyfriend = new BoyFriend();
        Friend girlfriend = new GirlFriend(); // 객체 타입과 참조변수 타입의 불일치
//GirlFriend friend1 = new Friend(); -> 하위클래스 타입으로 상위클래스 객체 참조 -> 불가능

				friend.friendInfo();
        boyfriend.friendInfo();
        girlfriend.friendInfo();

// 출력값 : 각 객체에 정의한 메소드 내용 출력
  • 참조변수가 사용할 수 있는 멤버의 개수는 상위 클래스의 멤버의 수가 된다.
    • ex) 위 예시의 GirFriend 클래스의 인스턴스를 생성하고 상위클래스인 Friend 타입의 참조변수에 할당 하였으므로 해당 참조변수 girfriend는 Friend 클래스의 멤버개수만큼 사용가능

참조변수의 타입 변환

정의

  • 사용할 수 있는 멤버의 개수를 조절하는 것

조건

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

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

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

  Car car = new Car();
  Vehicle vehicle = (Vehicle) car; // 상위 클래스 Vehicle 타입으로 변환(생략 가능)
  Car car2 = (Car) vehicle; // 하위 클래스 Car타입으로 변환(생략 불가능)
  MotorBike motorBike = (MotorBike) car; // 상속관계가 아니므로 타입 변환 불가 -> 에러발생

instanceof 연산자

  • 참조변수의 타입 변환, 즉 캐스팅이 가능한 지 여부를 boolean 타입으로 확인
  • 참조_변수 instanceof 타입
  • true가 나오면 참조 변수가 검사한 타입으로 타입 변환이 가능하며, 반대로 false
    가 나오는 경우에는 타입 변환

다형성의 활용 예제

void buyCoffee(Americano americano) { // 아메리카노 구입
	money = money - americano.price;
}

void buyCoffee(CaffeLatte caffeLatte) { // 카페라테 구입
  money = money - caffeLatte.price;
}
//커피의 종류가 한 두개가 아니라 수 십 수 백 가지가 된다면 그 경우에는 매번 새로운 타입을 매개변수로 전달해주는 buyCoffee 메서드를 계속 추가해주어야 한다.

void buyCoffee(Coffee coffee) { // 매개변수의 다형성
        money = money - coffee.price;
    }

// 매개변수로 각각의 커피 타입이 아니라 상위클래스인 Coffee 타입을 매개변수로 전달받으면,
// 그 하위클래스 타입의 참조변수면 어느 것이나 매개변수로 전달될 수있다.

추상화

정의

  • 기존 클래스들의 공통적인 요소들을 뽑아서 상위 클래스를 만들어 내는 것

장점

  • 공통적인 속성과 기능을 모아서 정의해주면 코드의 중복을 줄일 수 있고, 보다 효과적으로 클래스 간의 관계를 설정할 수 있으며, 유지/보수가 용이해집니다.

abstract 제어자

  • abstract : 추상적인, 미완성
  • 어떤 클래스에 추상 메서드가 포함되어있는 경우 해당 클래스는 자동으로 추상 클래스가 된다.
abstract class AbstractExample { // 추상 메서드가 최소 하나 이상 포함돼있는 추상 클래스
	abstract void start(); // 메서드 바디가 없는 추상메서드
}

AbstractExample abstractExample = new AbstractExample(); // 에러발생.

추상 클래스

정의

  • 추상 메서드를 포함하는 ‘미완성 설계도’
  • 객체를 생성하는 것이 불가능
  • 추상메서드와 구현메서드를 가질 수있다.

장점

  • 상속 관계에 있어 새로운 클래스를 작성하는데 매우 유용
  • 상속을 받는 하위 클래스에서 오버라이딩을 통해 각각 상황에 맞는 메서드 구현이 가능하다.
abstract class Animal {
	public String kind;
	public abstract void sound();
}

class Dog extends Animal { // Animal 클래스로부터 상속
	public Dog() {
		this.kind = "포유류";
	}

	public void sound() { // 메서드 오버라이딩 -> 구현부 완성
		System.out.println("멍멍");
	}
}

class Cat extends Animal { // Animal 클래스로부터 상속
	public Cat() {
		this.kind = "포유류";
	}

	public void sound() { // 메서드 오버라이딩 -> 구현부 완성
		System.out.println("야옹");
	}
}

final 키워드

  • 클래스, 메서드, 변수 앞에 final 제어자가 추가되면 해당 대상은 더이상 변경이 불가하거나 확장되지 않는다.
위치의미
클래스변경 또는 확장 불가능한 클래스, 상속 불가
메서드오버라이딩 불가
변수값 변경이 불가한 상수

인터페이스

정의

  • 서로 다른 두 시스템, 장치, 소프트웨어 따위를 서로 이어주는 부분 또는 그런 접속 장치
  • 추상클래스 - ‘미완성 설계도’ / 인터페이스 - 기초적인 “밑그림”
  • 추상 메서드와 상수만을 멤버로 가질 수 있다
  • Java 8 이후에 default / static 메서드를 인터페이스에 포함시킬수 있다.

장점

  • 기능의 선언과 구현을 분리 → 복잡한 구현의 내용 또는 변경과 상관없이 해당 기능을 사용할 수 있다
  • 독립적인 프로그래밍을 ****통해 한 클래스의 변경이 다른 클래스에 미치는 영향을 최소화
    할 수 있다

기본 구조

  • class 키워드 대신 interface 키워드를 사용
  • 내부의 모든 필드가 public static final로 정의
  • 모든 메서드가 public abstract로 정의
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 생략
}

// 접근제어자 및 키워드 생략가능 -> 컴파일러가 자동으로 추가

구현

  • 객체 생성 불가
  • implements키워드를 사용
class 클래스명 implements 인터페이스명 {
		... // 인터페이스에 정의된 모든 추상메서드를 오버라이딩하여 구현
}

다중 구현

  • 인터페이스는 다중상속이 가능(클래스는 불가)

클래스는 다중상속이 안되고 인터페이스는 가능한 이유

  • 클래스는 부모 클래스에 동일한 이름의 필드 또는 메서드가 존재하는 경우 충돌이 발생
  • 인터페이스는 애초에 미완성된 멤버를 가지고 있기 때문에 충돌이 발생할 여지가 없다.
interface Animal { // 인터페이스 선언. public abstract 생략 가능.
	public abstract void cry();
} 

interface Pet {
	void play();
}

class Dog implements Animal, Pet { // Animal과 Pet 인터페이스 다중 구현
    public void cry(){ // 메서드 오버라이딩
        System.out.println("멍멍!"); 
    }

    public void play(){ // 메서드 오버라이딩
        System.out.println("원반 던지기");
    }
}
  • 클래스는 다른 클래스로부터의 상속을 받으면서 동시에 인터페이스를 구현가능
abstract class Animal { // 추상 클래스
	public abstract void cry();
}
interface Pet { // 인터페이스
	public abstract void play();
}

class Dog extends Animal implements Pet { // Animal 클래스 상속 & Pet 인터페이스 구현
    public void cry(){
        System.out.println("멍멍!");
    }

    public void play(){
        System.out.println("원반 던지기");
    }
}

어려운 내용(에러)


문제

해결

profile
백엔드 개발자

0개의 댓글