15일차 다형성, 추상클래스, 인터페이스
타입변환과 다형성
(1)다형성 (多形性, Polymorphism)
-같은 타입이지만 실행 결과가 다양한 객체 대입(이용) 가능한 성질
1)부모 타입에는 모든 자식 객체가 대입 가능
(자식 타입은 부모 타입으로 자동 타입 변환)
2)효과: 객체 부품화 가능
(2)자동 타입 변환(Promotion)
-프로그램 실행 도중에 자동 타입 변환이 일어나는 것
-바로 위의 부모가 아니더라도 상속 계층의 상위면 자동 타입 변환 가능
(변환 후에는 부모 클래스 멤버만 접근 가능)
(3)필드의 다형성
-다형성을 구현하는 기술적 방법
1)부모 타입으로 자동 변환 (다형성1)
2)재정의된 메소드(오버라이딩) (다형성2)
---------------------부모 클래스 형성 ------------------------
package polymorphismex;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Animal01 {
void sound() { //자식객체에 물려줄 인스턴스 메소드
System.out.println("Animal::sound() invoked.");
}//sound
}//end class
---------------------자식 클래스 형성 ------------------------
package polymorphismex;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Dog02 extends Animal01 {
@Override
void sound() {
System.out.println("Dog::sound() invoked.");
}//sound
void dogMethod() {
System.out.println("bow - wow");
}// dogMethod
}//end class
---------------------부모 클래스2 형성 ------------------------
package polymorphismex;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Cat03 extends Animal01 {
@Override
void sound() {
System.out.println("Cat::sound() invoked.");
}//sound
void catMethod() {
System.out.println("CCCCCCAAAAAAAAKKKKKKK");
}// dogMethod
}//end class
-----------------------------다형성 실행---------------------------
package polymorphismex;
public class PPP04 {
public static void main(String[] args) {
// 1. 다형성-1: 부모타입의 참조변수에 모든 자식객체 대입이 가능
Animal01 animal = new Dog02(); // OK
System.out.println("1)animal: " + animal);
//2. 다형성-2: 부모타입의 참조변수의 메소드를 호출할 때,
// 무조건 자식객체가 재정의한 메소드가 호출된다.
// animal.dogMethod(); xx
animal.sound();
// ----
animal = new Cat03(); // 클래스 본판 변경!
System.out.println("2)animal: " + animal);
// animal.catMethod(); xx
animal.sound();
}//main
}//end class
(4)매개변수의 다형성
-매개변수가 클래스 타입일 경우
1)해당 클래스의 객체 대입이 원칙이나 자식 객체 대입하는 것도 허용
(자동 타입 변환)(매개변수의 다형성)
---------------------------부모 클래스 형성-------------------------
package polymorphismex02;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Vehicle {
public void run() {
System.out.println("Vehicle::run() invoked.");
}//run
}// end class
---------------------------자식 클래스 형성-------------------------
package polymorphismex02;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Bus02 extends Vehicle{
@Override
public void run() {
System.out.println("Bus::run() invoked.");
}//run
}//end class
---------------------------자식 클래스 형성-------------------------
package polymorphismex02;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Taxi03 extends Vehicle{
@Override
public void run() {
System.out.println("Taxi::run() invoked.");
}//run
}//end class
---------------------------매개변수 다형성 실행-------------------------
package polymorphismex02;
public class DriverEx05 {
public static void main(String[] args) {
DriverEx05 dr = new DriverEx05();
Bus02 bus = new Bus02(); // 자식객체 생성
Taxi03 taxi = new Taxi03(); // 자식객체 생성
dr.drive(bus); // 매개변수는 부모클래스 자식객체를 인자로 전달
dr.drive(taxi); // 매개변수는 부모클래스 자식객체를 인자로 전달
}//main
public void drive(Vehicle vehicle) {
System.out.println("Driver::drive(vehicle) invoked.");
vehicle.run();
}// drive
}// end class
(5)강제 타입 변환(Casting)
-부모 타입을 자식 타입으로 변환하는 것
-조건
자식 타입을 부모 타입으로 자동 변환 후, 다시 자식 타입으로 변환할 때
-강제 타입 변환 이 필요한 경우
1)자식 타입이 부모 타입으로 자동 변환
(부모 타입에 선언된 필드와 메소드만 사용 가능)
2)자식 타입에 선언된 필드와 메소드를 다시 사용해야 할 경우
---------------------------자식 클래스 형성-------------------------
package ex_04_12.casting;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Child extends Parent{
public String field2;
public void method3() {
System.out.println("parent::method3 invoked.");
}// me3
}// class end
---------------------------자식 클래스 2 형성-------------------------
package ex_04_12.casting;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Child2 extends Parent{
public String field3;
public void method4() {
System.out.println("parent::method3 invoked.");
}// me3
}// class end
---------------------------부모 클래스 형성-------------------------
package ex_04_12.casting;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class Parent {
public String field1;
public void method1() {
System.out.println("parent::method1 invoked.");
}//me1
public void method2() {
System.out.println("parent::method2 invoked.");
}// me2
}// class end
--------------------------- Casting-------------------------
package ex_04_12.casting;
public class ChildEx {
public static void main(String[] args) {
Parent parent = new Child();
parent.field1 = "data1";
parent.method1();
parent.method2();
// -----------
// parent.field2 = "data2"; 에러
// parent.method3() ; 에러
// 이유: 부모클래스에는 해당 필드와 메소드가 없고 이를 참조타입으로 삼았기 때문에 안됌.
// -------
// 자식객체 고유의 필드와 메소드를 사용해야 할 때에는 어떻게 합니까 ?
Child child =(Child) parent; // 다형성-1이 전제조건하에서 , 자식객체를 빼낼 때 필요
//단 child 1인지 2인지 3인지 자식이 무수히 많을 때 정확하지 않을 수도 있다.
child.field2 = "yyy"; //가능
child.method3(); //
// -------정확하지 않음에 검사해주는 instanceof를 사용한다.
if(parent instanceof Child) {
Child child2 = (Child) parent;
child2.field2 = "yyy"; //가능
child2.method3(); //가능
}// if
// 이는 자바에 엄청나게 부담이 되기때문에 이를 해결하기위해 제네릭이 나옴
}//main
}//end class
추상 클래스(Abstract Class)
(1)추상 클래스 개념
-
실체들 간에 공통되는 특성을 추출한 것
-
추상 클래스(abstract class)
1)실체 클래스들의 공통되는 필드와 메소드 정의한 클래스
2)추상 클래스는 실체 클래스의 부모 클래스 역할 (단독 객체 X)
(2)추상 클래스의 용도
-실체 클래스의 공통된 필드와 메소드의 이름 통일할 목적
(1)실체 클래스를 설계자가 여러 사람일 경우,
(2)실체 클래스마다 필드와 메소드가 제각기 다른 이름을 가질 수 있음
-실체 클래스를 작성할 때 시간 절약
(1)실체 클래스는 추가적인 필드와 메소드만 선언
-실체 클래스 설계 규격을 만들고자 할 때
(1)실체 클래스가 가져야 할 필드와 메소드를 추상 클래스에 미리 정의
(2)실체 클래스는 추상 클래스를 무조건 상속 받아 작성
(3)추상 클래스 선언(abstract 키워드 )
-New 연산자로 객체 생성하지 못하고 상속 통해 자식 클래스만 생성 가능
(4)추상 메소드와 오버라이딩(재정의)
-메소드 이름 동일하지만, 실행 내용이 실체 클래스마다 다른 메소드
-구현 방법
1)추상 클래스에는 메소드의 선언부만 작성 (추상 메소드)
2)실체 클래스에서 메소드의 실행 내용 작성(오버라이딩(Overriding))
----------------------------추상클래스/메소드 선언 ---------------------------
package ex_04_12.abstractex;
public abstract class Animal { //객체를 직접 생성 불가
public String kind;
public void breathe() {
System.out.println("Animal::breathe() invoked.");
} // breathe
//추상메소드란? 구현 block이 없이 메소드 선언부만 있는 경우를 의미
public abstract void sound(); // 추상메서드 : 강제규격 (To 자식 재정의를...)
}// end class
---------------------------오버라이딩 및 추상메서드 구현------------------------
package ex_04_12.abstractex;
public class Cat extends Animal {
public Cat() {
this.kind= "포유류";
}
// 무조건 재정의 하거나 자식도 abstract 지정해준다.
@Override
public void sound() {
System.out.println("야옹");
};
}// end class
인터페이스
(1)인터페이스
-개발 코드와 객체가 서로 통신하는 접점
(개발 코드는 인터페이스의 메소드만 알고 있으면 된다.)
-인터페이스의 역할
개발 코드가 객체에 종속되지 않게 -> 객체 교체할 수 있도록 하는 역할
개발 코드 변경 없이 리턴값 또는 실행 내용이 다양해 질 수 있음 (다형성)
(2)인터페이스 선언
-interface 식별자 관례 - class 규칙 따르면서 앞에 i를 붙여서 인터페이스임을 구별
-인터페이스에 선언된 필드는 모두 public static final
-선언과 동시에 초기값 지정(static { } 블록 작성 불가)
-추상 메소드 선언
-디폴트 메소드 선언
-정적 메소드 선언
--------------------------인터페이스 선언 ---------------------------
package ex_04_12.interfaceex;
//1. member : static final 상수 선언
//2. member : 추상 메소드 선언
//3. member : default 메소드 (기본 메소드 )
//4. member : static 메소드 (공용 메소드 )
public interface RemoteControl {
public static final int MAX_VOLUME =10;
int MIN_VOLUME =0; // interface에서는 접근제한자 static final이 생략된다. 컴파일러가 자동으로 붙임
//하지만 이렇게 적어주지말자 오해한다.
//추상메서드 : 자식클래스에서 반드시 재정의시킬 강제 규격
void turnOn(); // public abstract가 생략 가능 하지만 생략하지마라!
public abstract void turnOff();
public abstract void setVolume(int volume);
//default 메소드
public default void setMute(boolean mute) {
if(mute) {
System.out.println("무음을 처리합니다");
} else {
System.out.println("무음을 해제합니다");
}// if - else
}//setmute
//정적 메소드
public static void changeBattery() {
System.out.println("베터리를 교체합니다");
}//changeBattery
} // end interface
(3)인터페이스 구현
-구현 객체와 구현 클래스
(인터페이스의 추상 메소드 대한 실체 메소드를 가진 객체 = 구현 객체)
(구현 객체를 생성하는 클래스 = 구현 클래스)
-구현 클래스 선언
자신의 객체가 인터페이스 타입으로 사용할 수 있음(implements 키워드)
-추상 메소드의 실체 메소드를 작성하는 방법
메소드의 선언부가 정확히 일치해야한다.
(일부만 재정의할 경우, 추상 클래스로 선언)
------------------------------인터페이스 구현 클래스1 생성------------------------
package ex_04_12.interfaceex;
import lombok.NoArgsConstructor;
//인터페이스: "부모", 구현클래스: "자식"
@NoArgsConstructor
public class Television implements RemoteControl{
//필드
private int volume;
@Override
public void turnOn() {
System.out.println("Audio를 켭니다.");
};
@Override
public void turnOff() {
System.out.println("Audio를 끕니다.");
};
@Override
public void setVolume(int volume) {
if(volume > RemoteControl.MAX_VOLUME) {
this.volume = RemoteControl.MIN_VOLUME;
} else if(volume < RemoteControl.MIN_VOLUME) {
this.volume = RemoteControl.MAX_VOLUME;
}else {
++volume;
}
}// setVolume
}// end class
------------------------------인터페이스 구현 클래스2 생성------------------------
package ex_04_12.interfaceex;
import lombok.NoArgsConstructor;
//인터페이스: "부모", 구현클래스: "자식"
@NoArgsConstructor
public class Audio implements RemoteControl{
//필드
private int volume;
@Override
public void turnOn() {
System.out.println("Audio를 켭니다.");
};
@Override
public void turnOff() {
System.out.println("Audio를 끕니다.");
};
@Override
public void setVolume(int volume) {
if(volume > RemoteControl.MAX_VOLUME) {
this.volume = RemoteControl.MIN_VOLUME;
} else if(volume < RemoteControl.MIN_VOLUME) {
this.volume = RemoteControl.MAX_VOLUME;
}else {
++volume;
}
}// setVolume
}// end class
(4)인터페이스 사용
-추상 메소드 (실제 구현된 객체에서)
-디폴트 메소드
1)인터페이스만으로는 사용 불가(인스턴스메소드)
2)모든 구현 객체가 가지고 있는 기본 메소드로 사용
-정적 메소드
인터페이스로 바로 호출 가능 (인터페이스명.메소드명)
--------------------------인터페이스 구현 클래스 사용 ----------------------------
package ex_04_12.interfaceex;
public class RemoteControlExample {
public static void main(String[] args) {
// TODO Auto-generated method stub
RemoteControl rc;
rc = new Television(); //다형성 1
System.out.println("1. rc: " + rc);
rc.turnOn(); // 다형성 2
rc = new Audio(); // 다형성 1
System.out.println("1. rc: " + rc);
rc.turnOn();
} // main
} // end class
(5)익명 구현 객체
-명시적인 구현 클래스 작성 생략하고 바로 구현 객체를 얻는 방법
(이름 없는 구현 클래스 선언과 동시에 객체 생성)
(인터페이스의 추상 메소드들을 모두 재정의하는 실체 메소드가 있어야 한다)
------------------------------------익명 구현 객체 사용 ------------------------------
package ex_04_12.interfaceex.noname;
public class RemoteControlExample {
public static void main(String[] args) {
//익명 구현 rc에 저장
RemoteControl rc = new RemoteControl() {
String name = "kkk";
int age = 23;
public void myMethod() {
System.out.println("Anonymous::myMethod() intvoked.");
}
@Override
public void turnOn() {
System.out.println("Anonymous::turnOn() intvoked.");
System.out.println("\t + name:" + name);
}//turnOn
@Override
public void turnOff() {
System.out.println("Anonymous::turnOff() intvoked.");
System.out.println("\t + name:" + age);
}//turnOff
@Override
public void setVolume(int volume) {
System.out.println("Anonymous::setVolume() intvoked.");
}//setVolume
};
System.out.println(rc);
//다형성 -2
rc.turnOn();
rc.setVolume(10);
rc.turnOff();
//인터페이스를 통한 모든 구현객체의 기능 확장
rc.setMute(true); //default 메소드
RemoteControl.changeBattery(); // static 메소드
// ----
// System.out.println(rc.name); 익명객체에서 구현된 오버라이딩 외의 멤버는 밖에서 사용 불가능
// System.out.println(rc.myMethod);
}//main
} // end class
(6)다중 인터페이스 구현 클래스 /인터페이스간 상속
-다중 인터페이스 구현 클래스는 인터페이스의 실체 메소드 모두 구현
-하위 인터페이스 구현 클래스는 아래 추상 메소드를 모두 재정의해야
---------------------------------인터페이스와 상속 동시 예제 -----------------------
--------------------------------인터페이스 생성 -------------------------------
package ex_04_12.multi;
public interface Searchable {
public abstract void search(String url);
}// end interface
-------------------------------클래스 생성--------------------------------
package ex_04_12.multi;
import ex_04_12.interfaceex.RemoteControl;
public class SmartTelevision {
private int volume;
public void turnOn() {
System.out.println("Audio를 켭니다.");
}; // t on
public void turnOff() {
System.out.println("Audio를 끕니다.");
};// t off
public void setVolume(int volume) {
if(volume > RemoteControl.MAX_VOLUME) {
this.volume = RemoteControl.MIN_VOLUME;
} else if(volume < RemoteControl.MIN_VOLUME) {
this.volume = RemoteControl.MAX_VOLUME;
}else {
++volume;
}
}// setVolume
}//class
-----------인터페이스와 클래스 상속을 받는 클래스 생성----------------------
package ex_04_12.multi;
public class SmartTvEx extends SmartTelevision implements Searchable {
public static void main(String[] args) {
SmartTelevision tv = new SmartTvEx();
tv.turnOn();
// tv.search("naver.com") SmartTelevision에 메소드 정의 안되어있어서 안됌
Searchable Stv= (Searchable) tv;
Stv.search("naver.com");
// Stv.turnOn(); Searchable 에는 메소드 정의 안되어있어서 안됌
SmartTvEx smart = (SmartTvEx) Stv;
smart.turnOn();
smart.turnOff();
smart.search("naver.com");
}//main
@Override
public void search(String url) {
System.out.println(url);
} // search
}//class
(7)디폴트 메소드와 인터페이스 확장
-디폴트 메소드와 확장 메소드 사용하기
-디폴트 메소드가 있는 인터페이스 상속
-부모 인터페이스의 디폴트 메소드를 자식 인터페이스에서 활용 방법
1)디폴트 메소드를 단순히 상속만 받음
2)디폴트 메소드를 재정의(Override)해서 실행 내용을 변경
3)디폴트 메소드를 추상 메소드로 재선언
-------------------------------------다중인터페이스와 인터페이스끼리의 상속 ----------------------------
------------------------부모 인터페이스 생성-------------------------
package ex_04_12.interface_extends;
public interface A {
public abstract void methodA();
}
------------------------부모 인터페이스 생성-------------------------
package ex_04_12.interface_extends;
public interface B {
public abstract void methodB();
public default void methodBB() {
}
}
----------------2명의 부모를 가진 자식 인터페이스 생성/ 디폴트 메소드 추상화--------------------
package ex_04_12.interface_extends;
public interface C extends A,B{ // 인터페이스의 상속은 여러개 가능
public abstract void methodC();
// @Override
// public abstract void methodBB(); //default 추상메서드로 재선언
}
-------------------인터페이스들과 아무 관계 없는 인터페이스 ----------------
package ex_04_12.interface_extends;
public interface D {
public abstract void methodD();
}
------------------------모두를 최종으로 다중 상속받는 클래스/디폴트 재선언-----------------
package ex_04_12.interface_extends;
public class Cplaing implements C,D{
@Override
public void methodA() {
System.out.println("A구현");
}//A 주석처리하면 오류난다.
@Override
public void methodB() {
System.out.println("B구현");
}//B 주석처리하면 오류난다. 이유: C가 A,B를 상속했기 때문에
@Override
public void methodC() {
System.out.println("C구현");
}//C
@Override
public void methodBB() {} // 상속받은 default 메소드 실행내용을 변경
@Override
public void methodD() {
}
}
--------------------------최종 사용 예제 --------------------------------
package ex_04_12.interface_extends;
public class Example {
public static void main(String ... args) {
Cplaing ex = new Cplaing(); //구현 객체 생성.
A a = ex ; // 할아버지 인터페이스
a.methodA();
B b = ex; // 할머니 인터페이스
b.methodB();
C c = ex; // 부모 인터페이스
c.methodC();
c.methodB();
c.methodA();
c.methodBB();
//구현 객체만 생성하면 조상의 조상 인터페이스까지 참조타입으로 가능하다.
}//main
}//end class
Author And Source
이 문제에 관하여(15일차 다형성, 추상클래스, 인터페이스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@koo9b9h/15일차-다형성-추상클래스-인터페이스저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)