반응형
다형성
- 여러 가지 형태를 가질 수 있는 능력
- 한 타입의 참조변수로 여러 타입의 객체를 참조
- 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하는 것
- 조상 타입 참조 변수로 자손 타입 객체를 다루는것
Tv t = new Tv();
SmartTv() s = new SmartTv();
class Tv{
boolean power; // 전원상태 (on/off)
int channel; // 채널
void power() { power = !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
class SmartTv extendsTv {
String text; // 캡션(자막)을 보여 주기 위한 문자열
void caption() { /* 내용생략 */ }
}
객체와 참조변수의 타입이 일치할 때와 일치하지 않을 때의 차이점
SmartTv s = new SmartTv(); // 참조 변수와 인스턴스의 타입이 일치
Tv t = new SmartTv(); // 조상 타입 참조변수로 자손 타입 인스턴스 참조
둘 다 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.
- 반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조 불가능하다.
- 그 이유는 실제 인스턴스의 Tv의 멤버 개수보다 참조변수 c가 사용할 수 있는 멤버 개수가 더 많기 때문이다.
- 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야한다.
참조변수의 형변환
- 사용할 수 있는 멤버의 갯수를 조절하는 것
- 기본형 변수와 같이 참조변수도 형변환이 가능 단, 서로 상속관계에 있는 클래스사이에서만 가능
- 조상의 조상으로도 형변환 가능 모든 참조변수는 모든 클래스의 조상인 Object클래스로 가능
자손 타입 → 조상타입 : 형변환 생략 가능조상타입의 참조변수를 자손타입의 참조변수로 변환하는 것을 다운 캐스팅(down-casting) 이라고 하며, 자손타입의 참조변수를 조상타입의 참조변수로 변환하는 것을 업캐스팅(up-casting)이라고한다
- 자손 타입 ← 조상타입 : 형 변환 생략 불가능
- A. 참조변수로 사용할 수 있는 멤버의 갯수가 달라집니다.
- A. 아닙니다. 일치하는 것이 보통이지만 일치 하지 않을 수도 있습니다.
- 조상 타입 참조변수는 공통으로 사용할것을 남두고 자손 타입은 다른 기능들을 넣어준다.
public static void main(String[] args) {
Car car =null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null;
fe.water();
car =fe; // car = (Car)fe; 에서 형변환이 생략됨
// car.water();
fe2 = (FireEngine)car; // 자손타입 <-조상타입. 형변환 생략 불가
fe2.water();
}
}
class Car{
String color;
int door;
void drive() { //운전하는 기능
System.out.println("drive,Brrr~");
}
void stop() { // 멈추는 기능
System.out.println("stop!!!");
}
}
class FireEngine extends Car { //소방차
void water() { //물을 뿌리는 기능
System.out.println("water!!!");
}
}
참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 떄문에 참조변수의 형변환은 인스턴스에 아무런 영향을 미치지 않는다
instanceof연산자
참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 intanceof연산자를 사용한다.
주로 조건문에 사용되며, instanceof의 왼쪽에는 참조변수를 오른쪽에서 타입(클래스명)이 피연산자로 위치한다
어떤 타입에 대한 instanceof연산의 결과가 true라는 것은 검사한 타입으로 형변환이 가능하다는 것을 뜻한다
package arabiannight.tistory.com.java.test;
public class Instanceof {
public static void main(String[] args) {
FireEngine f = new FireEngine();
Ambulance a = new Ambulance();
Instanceof test = new Instanceof();
test.doWork(f); test.doWork(a);
}
public void doWork(Car c) {
if (c instanceof FireEngine) {
FireEngine f = (FireEngine)c;
f.water();
} else if (c instanceof Ambulance) {
Ambulance a = (Ambulance)c;
a.siren();
}
}
}
class Car {
String color;
int door;
void drive() { //운전하는 기능
System.out.println("drive, brrrr~");
}
void stop() { // 멈추는 기능
System.out.println("stop!!!");
}
}
class FireEngine extends Car { // 소방차
void water() { // 물 뿌리는 기능
System.out.println("warter!!!");
}
}
class Ambulance extends Car { // 앰뷸런스
void siren() { // 사이렌을 울리는 기능
System.out.println("siren~~~~");
}
}
참조변수와 인스턴스의 연결
- 항상 실제 인스턴스의 메서드(오버라이딩된 메서드)가 호출되지만, 멤버변수의 경우 참조변수의 타입에 따라 달라진다.
- 멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우, 조상타입의 참조변수를 사용했을 대는 조상 클래스에 선언된 멤버변수가 사용되고, 자손타입의 참조변수를 사용했을 대는 자손 클래스에 선언된 멤버변수가 사용된다.
class BindingTest3{
public static void main(String[] args) {
Parent p = new Child();
Child c= new Child();
System.out.println("p.x = " + p.x);
p.method();
System.out.println();
System.out.println("c.x = " + c.x);
c.method();
}
}
class Parent {
int x= 100;
void method() {
System.out.println("Parent Method");
}
}
class Child extends Parent {
int x = 200;
void method() {
System.out.println("x=" + x); // this.x와 같다.
Syetem.out.println("super.x = " + super.x);
System.out.println("this.x=" + this.x);
}
}
매개변수의 다형성
다형성의 장점
- 다형성 매개변수
- 하나의 배열로 여러종류 객체다루기
- 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 하는것
- 참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
class Product {
int price; //제품가격
int bonusPoint; // 보너스 점수
Product(int price){
this.price = price;
bonusPoint = (int) (price/10.0); //보너스점수는 제품가격의 10%
}
}
class Tv extends Product {
Tv(){
// 조상클래스의 생성자 Product(int price)를 호출한다.
super(100); //Tv의 가격을 100만원으로 한다.
}
public String toString() { // Object클래스의 toString()을 오버라이딩한다.
return "Tv";
}
}
class Computer extends Product {
Computer(){
super(200);
}
public String toString() {
return "Computer";
}
}
class Buyer { // 물건사는 사람
int money = 1000; //소유금액
int bounsPoint = 0; //보너스 점수
void buy(Product p) {
if(money < p.price){
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price; // 가진 돈에서 구입한 제품의 가격을 뺸다
bounsPoint += p.bonusPoint; // 제품의 보너스 점수를 추가한다.
System.out.println(p + "을/를 구입하셨습니다.");
}
}
public class Ex7_8 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Buyer b = new Buyer();
b.buy(new Tv());
b.buy(new Computer());
System.out.println("현재 남은 돈은 " + b.money + "만원입니다.");
System.out.println("현재 보너스점수는 " +b.bounsPoint + "점입니다.");
}
}
여러 종류의 객체를 배열로 다루기
class Product {
int price; //제품의 가격
int bonusPoint; //제품구매 시 제공하는 보너스점수
Product(int price) {
this.price= price;
bonusPoint = (int)(price/10.0);
}
Product(){} //기본샌성자
}
class Tv extends Product {
Tv(){
super(100);
}
public String toString() { return "Tv"; }
}
class Computer extends Product {
Computer() { super(200) ;}
public String toString() { return "Computer"; }
}
class Audio extends Product {
Audio() { super(50); }
public String toString() { return "Audio"; }
}
class Buyer { //고객,물건을 사는 사람
int money = 1000; //소유금액
int bonusPoint = 0; //보너스 점수
Product[] item = new Product[10]; // 구입한 제품을 저장하기 위한 배열
int i = 0; // Product배열에 사용될 카운터
void buy(Product p) {
if(money < p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price; //가진 돈에서 구입한 제품의 가경을 뺀다.
bonusPoint += p.bonusPoint; //제품의 보너스 점수를 추가한다.
item[i++] = p; //제품을 Product[] item에 저장한다.
System.out.println(p + "을/를 구입하셨습니다.");
}
void summary() { // 구매한 물품에 대한 정보를 요약해서 보여 준다.
int sum = 0; // 구입한 물품의 가격합계
String itemList = ""; //구입한 물품목록
//반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
for(int i =0; i< item.length; i++) {
if(item[i] ==null) break;
sum += item[i].price;
itemList += item[i] + ", ";
}
System.out.println("구입한신 물품의 총금액은 " + sum + "만원입니다.");
System.out.println("구입하신 제품은 " + itemList + "입니다.");
}
}
class PolyArgumentTest2 {
public static void main(String args[]){
Buyer b= new Buyer();
b.buy(new Tv());
b.buy(new Computer());
b.buy(new Audio());
b.summary();
}
}
총 정리
다형성
- 하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미합니다.
다형성(매개변수의 다형성)
한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 하는것
참조변수의 형변환
- 상속관계일 경우 조상과 자손의 참조변수는 형변환이 가능하다
- 단, 참조변수가 참조하고 잇는 인스턴스를 조심하자
(조상의 참조변수는 조상 인스턴스와 자손 인스턴스 둘 중 어떤 것을 참조 하고 있는지 모른다)
(이런 문제을 위해 instanceof연산자를 사용하여 형변환이 가능한지 검사 할 수 있다)
instanceof연산자
- 참조변수가 참조하는 인스턴스의 설계 타입을 체크하는데 사용
- 객체가 특정 클래스나 인터페이스로부터 생성된 개체인지를 판별하여 true또는 false값 반환
'Language > Java' 카테고리의 다른 글
오버로딩 vs 오버라이딩 (0) | 2021.09.19 |
---|---|
추상화 (0) | 2021.09.19 |
상속, 패키지, 접근 제어자 (0) | 2021.09.16 |
Static (0) | 2021.09.12 |
객체지향 언어 (0) | 2021.09.12 |