본문 바로가기
🌈 백엔드/객체 지향

JAVA_객체지향_다형성 & 업캐스팅 & 다운캐스팅

by 개발자 알마 2023. 6. 18.
반응형

[1] 다형성


 

 

(1) 다형성 polymorphism

  • 객체지향 프로그래밍 특징
  • 다형성을 이용하여 유연하고 확장성, 유지보수가 편리한 코드를 설계할수 있다
  • 한 객체가 여러가지 타입을 가질수 있는것
  • 상위클래스에서 공통으로 적용가능한 하나의 코드를 이용하여 하위클래스에서는 오버라이딩을 적용하여 서로 다른 결과물을 반환하게 할수 있다 
  • 같은 코드에서 여러 다른 실행 결과가 나온다 
  • 유지보수시 상위클래스 변경으로 핸들링할수 있다 

 

 

[2] 업캐스팅 & 다운캐스팅


(1) 참조변수 형변환 : 캐스팅 

  • 타입을 변환하는 것
  • 상속 관계에 있는 상위클래스와 하위클래스 간에는 형변환이 가능하다 
  • 상속관계가 아니라면 형변환은 불가능하다
  • 멤버갯수를 조절하기 위해 업캐스팅 & 다운캐스팅을 한다 
  • 클래스타입 변수 = new 클래스생성자  

 

 

(2) 업캐스팅

  • 하위타입의 참조변수를 상위클래스 타입으로 형변환이 가능하고 () 생략이 가능하다
  • Car 의 메소드 drive(), stop()만 사용가능하고 water()는 사용불가하다  

 

(3) 다운캐스팅

  • 상위타입의 참조변수를 하위클래스 타입으로 형변환이 가능하고 () 무조건 있어야한다 
  • SportsCar의 메소드 drive(), stop() , water() 까지 다 사용가능

 

(4) instanceof 연산자 

참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용한다 

형변환이 가능하면 true, 불가하면 false 값으로 산출된다 

 

void work(Car c) {

	if ( c instanceof SportsCar) {
    
    		SportsCar test = (SportsCar) c ;
        
        	test.working();

 

 

(5) 캐스팅 예시

  • 원래 인스턴스의 형이 맞는지 여부를 체크하는 키워드 맞으면 true 아니면 false를 반환 하게하여 형변환을 확인한다 
// 상위 클래스 변수 = 하위 클래스 생성자 (가능)
Customer vc = new VIPCustomer();     

// 하위 클래스 변수 = 하위클래스 변수 (강제 형변환)
VIPCustomer vCustomer = (VIPCustomer)vc;
package 패키지;

import java.util.ArrayList;

// 공통 메서드
class Animal {
	
	public void move() {
		System.out.println("움직인다 ");
	}
}

//하위 오버라이딩 
class Human extends Animal {
	@Override
	public void move( ) {
		System.out.println("사람이 걷는다 ");
	}
	public void readBook( ) {
		System.out.println("사람이 책을 읽는다 ");
	}
}

//하위 오버라이딩 
class Tigger extends Animal {

	@Override
	public void move( ) {
		System.out.println("호랑이가  걷는다 ");
	}
	public void hunting( ) {
		System.out.println("호랑이가 사냥한다  ");
	}	
}

//하위 오버라이딩 
class Eagle extends Animal {
	@Override
	public void move( ) {
		System.out.println("독수리가 난다  ");
	}
	public void flying( ) {
		System.out.println("독수리가 날개를 펼쳐 난다  ");
	}
}

 

public class AnimalTest {

	public static void main(String[] args) {
		
        //각 하위클래스의 인스턴스 생성 
		Animal humanAnimal = new Human();
		Animal tiggerAnimal = new Tigger();
		Animal eagleAnimal = new Eagle();
		
        //실행 인스턴스 생성 
		AnimalTest test = new AnimalTest();
		
		//출력하는 프로그램 
		ArrayList<Animal> animalList = new ArrayList<>();
		animalList.add(eagleAnimal);
		animalList.add(humanAnimal);
		animalList.add(tiggerAnimal);
		
		for(Animal animal : animalList) {
			animal.move();
		}
		test.downCasting(animalList);
	}
    
	//다운캐스팅 확인 작업 
	public void downCasting (ArrayList<Animal> list ) {
		for(int i =0; i <list.size(); i++) {
			Animal animal = list.get(i);
			
			if( animal instanceof Human) {
				Human human = (Human)animal;
				human.readBook();
			}else if(animal instanceof Tigger) {
				Tigger tigger = (Tigger)animal;
				tigger.hunting();
			}else if(animal instanceof Eagle) {
				Eagle eagle = (Eagle)animal ;
				eagle.flying();
			}else {System.out.println("인간이요 ");
		}
	}
	
	}
	
	public void moveAnimal(Animal animal) {
		animal.move();
	}

 

 

 

 

 

 

[3] 다형성 예시


 

(1) 하위 클래스 생성자 가능 

인스턴스 객체 생성시 상위클래스타입 = new 하위 클래스 생성자 가능

class Car {...} 

class SportsCar extends Car{..}

public static void main(String[] args) {

	Car Test1 = new Car();
    
    	sportsCar Test2 = new SportsCar();
    
    	Car Test3 = new SportsCar();
    	
        SportsCar Test4 = new Car(); (X) 
}

Test3은 타입은 같지 않지만 , 상위 타입의 참조변수로 하위 인스턴스를 참조한다 

이 경우 Car클래스의 멤버만 사용할수 있고 sportsCar 인스턴스의 멤버를 사용할수 없다 

 

(2) 상속 & 공통메서드의 overriding 

 

  • 공통 메서드 : move() 에 override한다 
  • 공통 메서드 실행 메서드 : moveplay()
package 패키지;

import java.util.ArrayList;


class Animal {
	
	public void move() {
		System.out.println("움직인다 ");
	} 
}


class Human extends Animal {
	
	@Override
	public void move( ) {
		System.out.println("사람이 걷는다 ");
	}
	
    public void readBook( ) {
		System.out.println("사람이 책을 읽는다 ");
	}
}


class Tigger extends Animal {
	
	@Override
	public void move( ) {
		System.out.println("호랑이가  걷는다 ");
	}
	public void hunting( ) {
		System.out.println("호랑이가 사냥한다  ");
	}
}


class Eagle extends Animal {
	
	@Override
	public void move( ) {
		System.out.println("독수리가 난다  ");
	}
	public void flying( ) {
		System.out.println("독수리가 날개를 펼쳐 난다  ");
	}
}

 

public class AnimalTest {

	public static void main(String[] args) {
		
        
		Animal humanAnimal = new Human();
		Animal tiggerAnimal = new Tigger();
		Animal eagleAnimal = new Eagle();
		
        //실행 인스턴스 객체 
		AnimalTest test = new AnimalTest();
		test.moveAplay(humanAnimal);
		test.moveAplay(tiggerAnimal);
		test.moveAplay(eagleAnimal);
		
		
        //다른방식으로 출력하기
		ArrayList<Animal> animalList = new ArrayList<>();
		animalList.add(eagleAnimal);
		animalList.add(humanAnimal);
		animalList.add(tiggerAnimal);
		
		System.out.println("<<for문으로 List 출력하기>> ");
		for(Animal animal : animalList) {
			animal.move();
		}
		
	}
	
    
	public void moveplay(Animal animal) {
		animal.move();
	}
}

 

(3) 캡슐화 & super() & 하위클래스의 overriding 

 

 

  • 각 등급별로 공통적으로 설정이 가능한 함수를 이용하여
  • 하위 클래스에 오버라이딩을 사용하여 어떤 클래스 타입의 인스턴스를 생성하는지에 따라
  • 출력되는결과물을 다르게 적용한다
일반 고객과 VIP 고객 중간 멤버십 만들기
고객이 늘어 일반 고객보다는 많이 구매하고 VIP보다는 적게 구매하는 고객에게도 해택을 주기로 했다.
GOLD 고객 등급을 만들고 혜택은 다음과 같다

제품을 살때는 10프로를 할인해준다
보너스 포인트는 2%를 적립해준다
  • 상위클래스 
package ch06;

public class Customer {

	protected int customerId;
	protected String customerName;
	protected String coustomerGrade;
	int bonusPoint;
	double bonusRatio; // 적립비율

	public Customer(int customerId, String customerName) {
		this.customerId =customerId;
		this.customerName = customerName;
		
		coustomerGrade ="Basic";
		bonusRatio = 0.01;
		
	}
	
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		return price;
	}
	
	public int getCustomerId() {
		return customerId;
	}

	public void setCustomerId(int customerId) {
		this.customerId = customerId;
	}

	public String getCustomerName() {
		return customerName;
	}

	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	public String getCoustomerGrade() {
		return coustomerGrade;
	}

	public void setCoustomerGrade(String coustomerGrade) {
		this.coustomerGrade = coustomerGrade;
	}

	public String showCustomerInfo() {
		return customerName +"님의 등급은 "+coustomerGrade + " 이고 , 보너스 포인트는 "+bonusPoint +"입니다 ";
	}
	
	
}
  • 하위클래스  : 골드 등급
package ch06;

public class GoldCustomer extends Customer {
	
	double salesRatio;
	
	public GoldCustomer (int customerId , String customerName) {
		super(customerId, customerName);
		
		coustomerGrade ="Gold";
		salesRatio = 0.1;
		bonusRatio =0.02;
	}
	
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		return price - (int)(price * salesRatio);
	}
}
  • 하위클래스 : vip 등급
package ch06;

public class VIPCustomer extends Customer {

	double salesRatio;
	String agentId;
	
	public VIPCustomer(int customerId , String customerName) { 
		super(customerId, customerName);
		
		coustomerGrade ="VIP";
		bonusRatio = 0.05;
		salesRatio = 0.1;
	}

	@Override
	public int calcPrice(int price) {
		bonusPoint += price * bonusRatio;
		price -= (int) (price * salesRatio);
		return price;
	}

	@Override
	public int getCustomerId() {
		return super.getCustomerId();
	}

	@Override
	public void setCustomerId(int customerId) {
		super.setCustomerId(customerId);
	}

	@Override
	public String getCustomerName() {
		return super.getCustomerName();
	}

	@Override
	public void setCustomerName(String customerName) {
		super.setCustomerName(customerName);
	}

	@Override
	public String getCoustomerGrade() {
		return super.getCoustomerGrade();
	}

	@Override
	public void setCoustomerGrade(String coustomerGrade) {
		super.setCoustomerGrade(coustomerGrade);
	}

	@Override
	public String showCustomerInfo() {
		return super.showCustomerInfo();
	}

	public String getAgentId() {
		return agentId;
	}

	public void setAgentId(String agentId) {
		this.agentId = agentId;
	}
}

 

  • 실행클래스 
package ch06;

import java.util.ArrayList;

public class Service {

	public static void main(String[] args) {
		
		ArrayList<Customer> customerList = new ArrayList<>();
		
		Customer customerA = new Customer(10010, "Tomas");
		Customer customerB = new Customer(10020, "James");
		Customer customerC = new GoldCustomer(10030, "kim");
		Customer customerD = new GoldCustomer(10040, "park");
		Customer customerE = new VIPCustomer(10050, "jin");
		
		customerList.add(customerA);
		customerList.add(customerB);
		customerList.add(customerC);
		customerList.add(customerD);
		customerList.add(customerE);
		
		for(Customer customer : customerList ) {
			System.out.println(customer.showCustomerInfo());
		}
		
		int price = 10000;
		for(Customer customer : customerList) {
			int cost = customer.calcPrice(price);
			System.out.println(customer.getCustomerName()+"님이 "+cost +"비용을 지불하였고 ");
			System.out.println("현재 보너스 포인트는 "+ customer.bonusPoint+"입니다 ");
		}
	}
}

 

(4) 참조변수를 매개변수로 & 상속 메서드 

공통으로 사용되는 buy 메소드에 (Tv c) 매개변수나 (Computer v) 매개변수를 개별로 사용하여 코드를 늘리는 것보다

(Product p)를 사용하여 하나의 메서드로 통일할수 있다 

메서드의 매개변수로 하위클래스의 매개변수는 상위클래스의 매개변수를 사용할수 있다 

class Product {
	int price;
    	int bonusPoint;
}
    
class Tv extends Product {}
class Computer extends Product {}

class Buyer {
	int money = 1000;
    	int bonusPoint =0;
}

buy(Product p) {

	money -= a.price;
    	bonusPoint += a.bonusPoint;
    
    
}

 

public static void main (String args[]) {


	Buyer b = new Buyer();
    
    	Tv a = new Tv();
    	Computer c = new Computer();
    
    	b.buy(a); // = b.buy(new Tv)
    	b.buy(c); // = b.buy(new Computer)

}

new Tv() , new Computer 가 참조변수이다 

 

(5) 참조변수를 배열로 

 

 

상위클래스

class Product {
	
	int price;
	int bonusPoint;

	Product(){};

	Product(int price) {
		this.price = price;
		bonusPoint = (int)(price* 0.1); 
	
	}	
}

 

하위클래스 TV

class Tv extends Product {

	Tv() {super(100);} //Tv의 price : 100 

	public String toString() { return "Tv";}
}

하위클래스 Computer

class Computer extends Product {
	
	Computer() {super(200);} //Computer의 price : 200 

	public String toString() { return "Computer";}
}

하위클래스 Audio

class Audio extends Product {
	
	Audio() {super(50);} //Audio의 price : 50 

	public String toString() { return "Audio";}
}

구매자 

class Customer {
	int money = 1000;
	int bonusPoint =0;
	Product [] productArr = new Product[10];
	int index =0;
	

	void buy(Product p) {
		if(money < p.price) {
			System.out.println("보유금액 부족 ");
			return;
	}
	
	money -= p.price;
	bonusPoint += p.bonusPoint;		
	
	productArr[index++] = p;
	System.out.println(p+"라는 물건을 구매하였습니다.");
	
	}
    
    	void customerInfo () {
		int buyPriceSum =0;
		String buyProduct ="";
	
		for(int i=0; i<productArr.length; i++) {
			if(productArr[i] == null) break;
				buyPriceSum += productArr[i].price;
				buyProduct += productArr[i]+",";
		}
	System.out.println("총구입금액은 " +buyPriceSum);
	System.out.println("구입상품은 " +buyProduct);
	}
}

메인 실행 클래스 

public class HelloJava {

	public static void main(String[] args) {
		
		Customer customerA = new Customer();
		
		customerA.buy(new Computer());
		customerA.buy(new Tv());
		customerA.buy(new Audio());
		customerA.customerInfo();

	}
	
}

반응형

댓글