[학습목표]
1. 객체지향 프로그래밍에 대한 개념을 이해합니다.
2. 클래스를 설계하는 방법에 대해 학습합니다.
3. 객체의 구성요소(필드, 메서드, 생성자)에 대해서 학습합니다.
4. 클래스 변수, 인스턴스 변수의 차이점에 대해서 학습합니다.
5. 생성자와 생성자 오버로딩에 대해 학습합니다.
6. this와 this() 키워드에 대해 학습합니다.
7. 접근 제어자에 대해 학습합니다.
8. pakage와 import에 대해 학습합니다.
9. 상속, 오버라이딩 을 통해 기능을 확장하는 방법을 배웁니다.
10. super와 super() 키워드에 대해 학습합니다.
11. 다형성의 원리와 구현 방법에 대해 학습합니다.
12. 추상 클래스에 대해 학습합니다.
13. 인터페이스의 역할에 대해 이해하고 구성 요소와 구현 방법에 대해 학습합니다.
14. 인터페이스의 디폴트 메서드와 static 메서드에 대해 학습합니다.
15. 인터페이스의 다형성 원리와 구현 방법에 대해 학습합니다.

1. 설계도(클래스)

객체란?

세상에 존재하는 물체, 식별이 가능한것
-특징과 행동 -> 속성과 행위 -> 필드와 메서드
-현실 세계 객체를 소프트웨어 객체로 설계하는 것 => 객체 모델링

< 객체간의 협력>

  • 사람과 자동차의 상호작용
  • 소프트웨어 객체들은 메서드를 통해 데이터를 주고 받음
  • 메소드 호출 시 괄호 안에 넣는 데이터 => 매개변수(파라미터, 입력값)
    메소드 종료 후 출력값(리턴값)

< 객체 간의 관계>

  • 사용 관계(사람 자동차)
  • 포함 관계(타이어,문,핸들 -> 자동차)
  • 상속 관계(자동차,기차 -> 기계시스템)

1)<객체 지향 프로그래밍 특징>

-캡슐화, 상속,다형성(여러개의 형태) ,추상화(구체적인것을 모호하게 뺌)

  1. 캡슐화(encapsulation)
  • 속성과 메서드를 묶어 객체로 만든 후 내부 내용(구조)을 외부가 알 수 없게 감추는 것(보안을 위해서)
  • 필드와 메소드를 통해 접근
  • 숨기는 이유는 객체가 변화하지 않게 만들기 위해
  • 객체의 필드와 필드와 메소드를 노출 시킬지->접근제어자(public, private, defalut 등등) 로 결정
  1. 상속
  • 부모와 자식 존재
  • 필드와 메서드를 자식에 물려줌(쓸지 안쓸지 자식의 의지에 따름)
  • 오버 라이딩 : 그대로 쓸것인지 or 가공해서 다르게 쓸것인지
  • 상속을 하는 이유
    구조 파악 쉬워짐
    일관성 유지
    코드 중복 줄어듬
  1. 다형성
  • 하나의 행위에 대해 객체가 가지고 있는 고유한 특성에 따라 여러가지 형태로 재구성
  • 메소드 구현 다르게 제정의 => 오버로딩(한 클래스 내에서 이름같은 메소드 여러개 정의)/오버라이딩(부모 클래스와 같은 메소드 자식내 에서 재정의)

C 언어에서는 매개변수 다르면 메소드명도 다르게 해줘야함!(절차지향언어)

제네릭(4주차)으로 한 메서드로 다른 타입도 재사용가능

**파이썬은 타입없음(인터프린터 언어) 빠름 ->코테에 유리

  1. 추상화(구체적인것->추상적으로 모호하게)
  • 객체에서 공통된 부분을 모아 상위 개념으로 새롭게 선언하는 것
  • 공통적이고 중요한것을 모아 객체를 모델링
    ex) 여러자동차의 자동차가 공통적으로 가지고 있는 가속,브레이크,속도

<객체와 클래스>
객체를 생성하기 위해서는 설계도 필요=> 클래스
클래스를 토대로 생성된 객체=> 인스턴스(과정을 인스턴스화)
new 키워드 사용

2)클래스 설계

<클래스 만드는 단계>
1.클래스 선언
2.객체 속성(필드) 정의
3.객체 생성 방식 정의(생성자,constructor)->인풋,로직
4.객체가 가지고 있어야할 행위 정의

생성자: 처음 객체가 생성될 때(인스턴스화) 어떤 로직을 수행하며, 어떤 값이 필수로 들어와야하는 지 정의! 클래스 이름과 동일

기본 생성자(매개변수 없는 생성자) : 생략이 가능

3)객체의 구성요소(필드와 메서드)

필드 메서드 생성자

필드

1.고유 데이터
2.상태 데이터
3.객체 데이터(객체 내에서 하위객체 가질수있다.)

선언 하고 초기화 하지 않으면 기본값으로

필드 사용방법

  • 객체 생성(인스턴스 화)를 시켜야 사용할 수 있음.
    1.외부 접근 : . 연산자로 접근
    Car car = new Car();
    car. color ="blue";
    2.내부 접근 : 클래스 내에서는 그냥 접근하면 됨
    breakPedal(){
    speed = 0;
    return speed;
    }
    내부에서 메소드 호출하 필드를 바로 호출 가능

메서드

정의(선언) 하는 방법

리턴타입 메서드명(매개변수,...){
	실행할 코드
    return 반환값;//리턴 타입 void아니면 반드시 있어야함
}

void
return; 없어도 되지만 있을 수 있다.(원하는 지점에서 메서드 종료)

input : 매개변수
output : return 값

input값 없으면 매개변수 생략 가능

가변길이 매개변수

void carSpeeds(double ... speeds) {
    for (double v : speeds) {
        System.out.println("v = " + v);
    }
}

몇개 들어와도 상관 없이 받을 수 있음

  • carSpeeds(100, 80);
  • carSpeeds(110, 120, 150);

<메서드 호출>
메서드 내부 코드 실행

외부 접근: car.breakPedal(); 매개변수 순서,타입에 맞게 넣어줘야함
내부 접근: 클래스 내부 메서드 내에서 사용.

오버로딩
한클래스에서 하나의 메서드 이름으로 여러기능을 구현
매개변수의 개수 또는 타입, 순서가 다게 작성

  • '응답 값만' 다른 것은 오버로딩을 할 수 없습니다.
  • 접근 제어자만 다른 것도 오버로딩을 할 수 없습니다.
  • 결론, 오버로딩은 매개변수의 차이로만 구현할 수 있습니다.
    장점: 메서드 이름 하나 상황에 따른 동작을 개별로 정의 ,이름절약
    ex)println()
    오버 라이딩
    부모 클래스의 메서드 재사용

4)기본형 매개변수 & 참조형 매개변수

  • 기본형 매개변수: 값자체 복사, 원본값 변경 안됨
  • 참조형 매겨변수: 주소를 전달, 원본값 변경

5)인스턴스 멤버 & 클래스 멤버

멤버 = 필드+메서드

선언하는 방법에 따라 구분
인스턴스 멤버는 객체 생성 후 사용가능, 클래스 멤버는 객체 생성 없이 사용

인스턴스 멤버

객체 생성해야 사용가능

  • 필드 : 각각 인스턴스 마다 고유하게 값을 가짐
  • 메서드 : 객체가 인스턴스 화 할때마다 메서드 생성X(메모리 효율)
    =>메서드 영역에 두고 인스턴스들이 공유하여 사용
    인스턴스를 통해서만 메서드가 사용되게 제한

클래스 멤버(static)

  • 클래스 : 클래스 로더에 의해 메서드 영역에 저장되고 사용
  • 클래스멤버: 메서드 영역의 클래스와 같은 위치에 고정적으로 위치
  • 객체 생성 없이 바로 사용

static 키워드 사용
-인스턴스마다 모두 가지고 있을 필요 없는 공용적인 데이터

인스턴스 메서드는 클래스 필드 사용할 수 있다.
클래스 메서드는 인스턴스 필드 사용하려고 하면 오류가 발생

클래스의 이름과 함께 도트(.) 연산자를 사용
Car.company = "Audi";
String companyName = Car.setCompany("Benz");

** 참조형 변수를 사용하여 클래스 멤버에 접근은 가능하지만 추천하지 않습니다. (클래스 이름으로 접근하는 것이 좋습니다.)

6)지역변수와 상수

지역변수<-> 전역변수

해당 메서드가 실행될 때마다 독립적인 값 저장,관리
메서드 내부에서 정의될 떄 생성, 메서드 종료될 때 소멸

상수

final (최종적) : 프로그램 실행 도중에는 절대로 수정 불가, 공용으로 쓰이는 값, 반드시 초기값 지정

상수(static final): 반드시 한개 불변의 값
인스턴스마다 상수저장 할 필요 없음.

(보통 전체 대문자로 표시)

7)생성자와 생성자 오버로딩

-객체 생성될 때 호출되며,객체 초기화

  • 기본 생성자는 ()안에 아무것도 넣지 않은 생성자=>new 키워드로 생성
  • 클래스에 생성자를 하나도 선언하지 않았다면 컴파일러는 기본 생성자를 바이트코드 파일에 자동으로 추가시켜줍니다. 따라서 이러한 경우는 기본 생성자 생략이 가능합니다.
    기본생성자없이 Car car =new Car();가능
  • 반대로 단 하나라도 생성자가 선언되어있다면 컴파일러는 기본 생성자를 추가하지 않습니다.
public class Car {
		public Car(String model) {} // 생성자 선언
		// 생성자가 한개 이상 선언되었기 때문에 기본 생성자를 추가하지 않음.
        //기본생성자없이=>Car car =new Car(); 하면 오류 발생
        //Car car = new Car("Benz");//로 생성해야함
}

-컴파일러에 의해 생성되는 기본 생성자는 해당 클래스의 접근 제어자(public, …)를 따릅니다.

public class Car {
		public Car() {} // 컴파일러가 추가시켜줌
}

class Car {
		Car() {} // 컴파일러가 추가시켜줌
}

필드 초기화와 생성자 오버로딩

생성자는 객체를 초기화 하는 역할

  • 객체를 만들때 인스턴스마다 다른 값을 가져야 한다면 생성자를 통해서 필드를 초기화 할 수 있습니다.
    • 예를 들어 만들어지는 자동차 마다 모델, 색상, 가격이 다르다면 생성자를 사용하여 필드의 값을 초기화 하는 것이 좋습니다.
public Car(String modelName, String colorName, double priceValue) {
    model = modelName;
    color = colorName;
    price = priceValue;
}

...
Car car1 = new Car("benz","white",2500.0);
Car car2 = new Car(); // 오류 발생->기본 생성자 만들지 않아서

8)this와 this() 키워드

this : 인스턴스 자신

public Car(String model, String color, double price) {
    model = model;
    color = color;
    price = price;
}
  • 매개변수명과 객체의 필드명이 동일할 경우 오류가 발생하지는 않지만 생성자 블록 내부에서 해당 변수들은 객체의 필드가 아닌 가장 가까운 매개변수명을 가리키게 됨으로 자기 자신에게 값을 대입하는 상황이 되어 버립니다.

=>해결

public Car(String model, String color, double price) {
   this.model = model;
   this.color = color;
   this.price = price;
}
  • 객체의 메서드에서 리턴타입이 인스턴스 자신의 클래스 타입이라면 this를 사용하여 인스턴스 자신의 주소를 반환할 수도 있습니다.
Car returnInstance() {
    return this;
}

this() : 인스턴스 자신의 생성자를 호출하는 키워드

  • 생성자를 통해 객체의 필드를 초기화할 때 중복되는 코드를 줄여줄 수 있습니다.
  • this() 키워드를 사용해서 다른 생성자를 호출할 때는 반드시 해당 생성자의 첫 줄에 작성되어야 합니다.
public Car(String model) {
    System.out.println("model = " + model);//오루
    this(model, "Blue", 50000000);
}

9)접근 제어자

[제어자]
클래스, 변수, 메서드의 선언부에 모두 사용가능

  • 접근 제어자 : public ,protected, defalut, private
  • 그 외 : static , final, abstract (추상화)

접근 제어자

지정되어 있지 않다면 default 입니다.

  • public : 접근 제한이 전혀 없습니다.
  • protected : 같은 패키지 내에서, 다른 패키지의 자손클래스에서 접근이 가능합니다.
  • default : 같은 패키지 내에서만 접근이 가능합니다.
  • private : 같은 클래스 내에서만 접근이 가능합니다.(보수적->캡슐화)

[사용가능한 접근 제어자]

  • 클래스 : public, default
  • 메서드 & 멤버변수 : public, protected, default, private
  • 지역변수 : 없음

[접근 제어자를 이용한 캡슐화 (은닉성)]

  • 접근제어자는 클래스 내부에 선언된 데이터를 보호하기 위해서 사용합니다.
  • 유효한 값을 유지하도록, 함부로 변경하지 못하도록 접근을 제한하는 것이 필요합니다.

[생성자의 접근 제어자]

  • 생성자에 접근 제어자를 사용함으로 인스턴스의 생성을 제한할 수 있습니다.

  • 일반적으로 생성자의 접근 제어자는 클래스의 접근 제어자와 일치합니다.

    ** Getter와 Setter

    객체의 무결성 즉, 변경이 없는 상태를 유지하기 위해 접근 제어자를 사용합니다.

  • 이때 외부에서 필드에 직접 접근하는 것을 막기 위해 필드에 private, default 등의 접근 제어자를 사용할 수 있습니다.

  • 객체의 private 필드를 읽고 쓰기 위해
    =>Getter(저장) 와 Setter(저장/수정) 를 사용

    인스턴스 메서드 호출과 동일

    [제어자의 조합]

  • 사용가능한 제어자
    - 클래스 : public, default, final, abstract
    - 메서드 : public, protected, default, private, final, abstract, static
    - 멤버변수 : public, protected, default, private, final, static
    - 지역변수 : final

    제어자 사용시 주의 사항

  • 메서드에 staticabstract를 함께 사용할 수 없다.

  • 클래스에 abstractfinal을 동시에 사용할 수 없다.

  • abstract메서드의 접근 제어자가 private일 수 없다.

  • 메서드에 privatefinal을 같이 사용할 필요는 없다.

10)package, import

package

클래스의 일부분이며, 하위 패키지를 도트(.)로 구분한다.

        week03.packageExample.pk1.Car car1 = new week03.packageExample.pk1.Car();
        week03.packageExample.pk2.Car car2 = new week03.packageExample.pk2.Car();

        car1.horn();
        car2.horn();

import

import week03.packageExample.pk1.Car;

public class Main {
 public static void main(String[] args) {
     //클래스의 일부분이며, 하위 패키지를 도트(.)로 구분한다.
     Car car= new Car();
     car.horn();
 }
}

2. 상속

1)상속

public class 자식클래스 extends 부모클래스 {

}

자칫하여 부모 클래스, 자식 클래스라는 용어에 현혹되어 ‘부모가 자식보다 큰 사람이니까 부모 클래스도 마찬가지로 자식 클래스 보다 큰 범위겠지?’ (X)

  1. 부모 클래스에 새로운 필드와 메서드가 추가되면 자식 클래스는 이를 상속받아 사용할 수 있다.
  2. 자식 클래스에 새로운 필드와 메서드가 추가되어도 부모 클래스는 어떠한 영향도 받지 않는다.(단방향)
  3. 따라서 자식 클래스의 멤버 개수는 부모 클래스보다 항상 같거나 많다.

클래스 간의 관계

상속 관계(is) : 고래(자식)는 포유류(부모)/스포츠카는 자동차이다.
포함 관계(has) : 자동차는 타이어,차문,핸들을 가지고 있다. =>클래스 내에 객체 변수로 생성

단일 상속, 다중상속

Java는 다중상속 허용 하지 않음. 한 부모만 상속
한 부모가 여러개의 자식 가질수잇음(한 자식이 여러부모 가질수 없음=>복잡해짐)

** C++ 다중상속(재사용성) 지원 : 부모가 같은 이름 변수나 메서드가지면 어떤 부모 참조해야할지 모름!->에러 (class 자체 상속)
Ruby : c++의 문제 해결해 다중상속 class namespace조합

fianl 클래스와 final 매서드(변경X)

부모클래스에 final키워드 지정하면 상속할 수 없는 클래스가됨
메서드에 final 키워드 지정하면 오버라이딩 할수 없는 메서드

Object 클래스

  • Object 클래스는 Java 내 모든 클래스들의 최상위 부모 클래스 입니다.
  • 따라서, 모든 클래스는 Object의 메서드를 사용할 수 있습니다.
  • 또한 부모 클래스가 없는 자식 클래스는 컴파일러에 의해 자동으로 Object 클래스를 상속받게 됩니다.

Object 클래스의 메서드

  • Object clone() : 해당 객체의 복제본을 생성하여 반환함.
  • boolean equals(Object object) : 해당 객체와 전달받은 객체가 같은지 여부를 반환함.
  • Class getClass() : 해당 객체의 클래스 타입을 반환함.
  • int hashCode() : 자바에서 객체를 식별하는 정수값인 해시 코드를 반환함.
  • String toString() : 해당 객체의 정보를 문자열
    로 반환함. & Object 클래스에서는 클래스이름 @해쉬코드값 리턴함.

2)오버라이딩과 super

오버라이딩

부모 클래스로부터 상속받은 메서드의 내용을 재정의 하는 것

부모 클래스의 메서드를 그대로 사용 가능하지만 자식 클래스의 상황에 맞게 변경을 해야하는 경우 오버라이딩을 사용합니다.

  1. 선언부가 부모 클래스의 메서드와 일치해야 합니다.
  2. 접근 제어자를 부모 클래스의 메서드 보다 좁은 범위로 변경할 수 없습니다.(더 넓은 범위로 가능)
  3. 예외는 부모 클래스의 메서드 보다 많이 선언할 수 없습니다.

//에노테이션
@Override

super와 super()

super : 부모클래스의 멤버(필드, 메서드)를 참조할 수 있는 키워드

super() : 부모 클래스의 생성자를 호출할 수 있는 키워드
부모 클래스의 생성자는 가장 첫 줄에서 호출이 되어야합니다.

-자식 클래스 객체를 생성할 때 생성자 매개변수에 매개값을 받아와 super(…)를 사용해 부모 생성자의 매개변수에 매개값을 전달하여 호출하면서 부모 클래스의 멤버를 먼저 초기화합니다.

  • 오버로딩된 부모 클래스의 생성자가 없다고 하더라도 부모 클래스의 기본 생성자를 호출해야합니다.
    - 따라서 눈에 보이지는 않지만 컴파일러가 super(); 를 자식 클래스 생성자 첫 줄에 자동으로 추가해 줍니다.
// 자식 클래스 SportsCar 생성자
public SportsCar(String model, String color, double price, String engine) {
     // this.engine = engine; // 오류 발생
    super(model, color, price);
    this.engine = engine;
}

3)다형성의 원리와 구현 방법

(1) 참조변수의 타입변환

  • 자동 타입변환

    • 부모타입 변수 = new 자식타입();(자식->부모로 형변환)
      => 인스턴스가 자식에만 있는 메소드 실행 불가
    • 오버라이딩은 적용됨
    • 부모타입 변수로 자식객체의 멤버에 접근할 때는 부모 클래스에 선언된 즉, 상속받은 멤버만 접근할 수 있습니다.

    자식타입 변수 = new 부모();//오류발생

  • 강제 타입변환
    자식타입 변수 = (자식타입) 부모타입객체;
    =>자식 메소드 실행가능

// 자식타입객체가 자동 타입변환된 부모타입의 변수
Mammal mammal = new Whale();
mammal.feeding();

// 자식객체 고래의 수영 기능을 사용하고 싶다면
// 다시 자식타입으로 강제 타입변환을 하면된다.
Whale whale = (Whale) mammal;
whale.swimming();
  • 다만 무조건 강제 타입변환을 할 수 있는 것은 아닙니다.
    - 자식타입객체가 부모타입으로 자동 타입변환된 후 다시 자식타입으로 변환될때만 강제 타입변환이 가능합니다.
    • 부모타입 변수로는 자식타입객체의 고유한 멤버를 사용할 수 없기 때문에 사용이 필요한 경우가 생겼을 때 강제 타입변환을 사용합니다.
Mammal newMammal = new Mammal();
Whale newWhale = (Whale) newMammal; // ClassCastException 발생

(2) 다형성이란?

여러가지 형태를 가질 수 있는 능력 => 참조변수 타입변환
ex) 자동차의 타이어교체, 바퀴교체

(3) instance of

다형성 기능으로 인해 해당 클래스 객체의 원래 클래스명 체크하는 것 필요=>이를 위해 사룡하는 명령어
(대상 객체) instance of (클래스 이름) 응답값은 boolean

Object => true
부모클래스 => true
형변환 했어도 => 원래 생성된 클래스 => true

4)추상 클래스

추상 클래스란?

클래스가 설계도라면 추상 클래스는 미완성된 설계도입니다.
abstract 키워드를 사용하여 추상 클래스를 선언할 수 있습니다.

    ```java
    public abstract class 추상클래스명 {
    
    }
    ```
    
    
  • 추상 클래스는 추상 메서드를 포함할 수 있습니다.

  • 추상 메서드가 없어도 추상 클래스로 선언할 수 있습니다.
    (일반 필드와 메서드도 가지고 있음 -> 그대로 사용)

    • 추상 클래스(부모,미완성)는 자식 클래스가 상속받아서 완성
    • 추상 클래스는 여러개의 자식 클래스들에서 공통적인 필드나 메서드를 추출해서 만들 수 있습니다.

    abstract는 클래스와 메서드에서만 사용 가능!!

추상 메서드

=>추상 클래스와 인터페이스(키워드 생략가능)에서 사용

추상 메서드는 아직 구현되지 않은 미완성된 메서드입니다.
abstract 키워드를 사용하여 추상 메서드를 선언할 수 있습니다.

```java
public abstract class 추상클래스명 {
		abstract 리턴타입 메서드이름(매개변수, ...);
}
```
  • 추상 메서드는 일반적인 메서드와는 다르게 블록{ }이 없습니다.
    • 즉, 정의만 할 뿐, 실행 내용은 가지고 있지 않습니다.

추상 클래스 상속

상속받은 클래스(자식)에서 추상 클래스의 추상 메서드는 반드시 오버라이딩 되어야 합니다.=>인터페이스랑 비슷

3. 인터페이스

1)인터페이스

역할

  • 두 객체를 연결해주는 다리
    예) 멀티 리모컨(티비가 교체되도 작동)
  • 상속 관계가 없는 다른 클래스들이 서로 동일한 행위(메서드) 구현 해야할 때 인터페이스는 구현 클래스들의 동일한 사용방법과 행위 보장
  • 스팩이 정의된 메서드들의 집합
  • 인터페이스 구현 클래스는 반드시 정의된 메서드 구현해야함
    => 다형성 적용

선언

public interface 인터페이스명 { 

}

인터페이스의 접근제어자는 무조건 public!! (생략해도 public으로 인지)

구성

모든 멤버 변수는 public static final (생략가능->컴파일러 자동추가)
=> 굳이 쓰지 않음! 차라리 추상클래스 사용!

모든 메서드 public abstrct(생략가능->컴파일러 자동추가)

but, static 메서드와 default메서드는 interface 내에 구현부분이 있어야함(추상 메서드 아님, public은 생략)

public interface 인터페이스명 { 
	public static final char A = 'A';
    static char B = 'B';
    final char C = 'C';
    char D = 'D';

    void turnOn(); // (public abstract) void turnOn();
}

구현

  • 직접 인스턴스 생성 못함-> 클래스에 구현되어 생성
    implements 키워드 사용해 구현
public class 클래스명 implements 인터페이스명 { 
			// 추상 메서드 오버라이딩
			@Override
	    public 리턴타입 메서드이름(매개변수, ...) {
			       // 실행문
	    }
}
  • 인터페이스의 추상 메서드는 구현될 때 반드시 오버라이딩 되어야 합니다
  • 만약 인터페이스의 추상 메서드를 일부만 구현해야 한다면 => 해당 클래스를 추상 클래스로 변경해주면 됩니다.

상속

  • 인터페이스 간 상속 가능 => extends 사용
  • 클래스와 달리 다중상속 가능
  • 인터페이스 구현(implements)와 상속(extends) 함께 사용 가능

2)인터페이스의 디폴트 메서드와 static 메서드(구현부분 있어야함)

디폴트 메서드

  • 추상 메서드의 기본적인 구현 제공하는 메서드
  • default 키워드, 블럭{} 존재
  • 접근제어자 public 생략가능
  • 구현 클래스에서 재정의 할 필요없이 사용!

static 메서드

  • 객체 없이 호출 가능 ( 인터페이스이름.method이름()로 호출)
  • 인터페이스 A,B 상속받은 C를 implements 했어도 A.aaa()로 호출해야함.
    => 굳이 사용 X

3)다형성

타입변환

자동 타입변환

인터페이스 변수 = 구현 객체;

public class Main {
    public static void main(String[] args) {
        
        // A 인터페이스에 구현체 B 대입
        A a1 = new B();
        
        // A 인터페이스에 구현체 B를 상속받은 C 대입
        A a2 = new C();
        
    }
}

interface A { }
class B implements A {}
class C extends B {}

강제 타입변환

구현 객체 변수 = (구현객체 타입) 인터페이스변수;

(인터페이스로 자동 타입 변환된 구현체 객체를) 다시 구현제로 변환할때만 강제타입변환 가능

인터페이스의 다형성

=>인터페이스 변수 = new 구현체
같은 변수로 구현체 쉽게 변경!

** 추상클래스& 인터페이스 는 인스턴스화가 안된다.
추상 클래스=>자식메서드 생성자로 생성 후 형변환
인터 페이스=>구현체의 생성자로 생성 후 형변환


인터페이스는 행위의 일관성
추상클래스는 일반화된 개념을 묶어준다!

0개의 댓글