[JAVA] 상속 - 2

김나영·2022년 8월 1일
2

업캐스팅 (Up-Casting)

  • 슈퍼클래스 객체 = new 서브클래스();
  • 서브클래스 객체를 슈퍼클래스 타입으로 변환하는 것
  • 자동으로 타입이 변환되는 promotion타입으로 변환하는 것
  • 업캐스팅된 서브클래스 객체는 슈퍼클래스의 메소드만 호출 가능
  • 슈퍼클래스 타입으로 저장은 가능하나 슈퍼클래스 내의 메소드만 호출 가능, 서브클래스의 메소드는 호출이 불가함
  • 오버라이드, 다운캐스팅을 통해 해결 가능
  • 여러 서브클래스를 하나의 슈퍼클래스로 처리하기 위해서는 배열을 사용한다.
Person[] people = new Person[10];
	people[0] = new Alba();
	people[1] = new Alba();
	people[2] = new Student();
	for(int i = 0; i < people.length; i++) {
		if(people[i] != null) {   //null 값은 제외 하기 위해 조건문 사용
		people[i].eat();
		people[i].study();
		people[i].work();
	}
}

향상 for문

for(Person person : people) {
	if(person != null) {
      person.eat();
      person.study();
      person.work();
	}
}

-연습문제 ( 버스 좌석 )

Seat[] seats = new Seat[25]; //null만 25개
seats[0] = new Seat();
seats[1] = new Seat();
seats[2] = new Seat();
...

Bus bus = new Bus(25); // 좌석(seat)이 25개인 버스
bus.ride(1.new Person("kim));
bus.ride(5.new Student("choi"));
bus.ride(10.new Alba("min"));
bus.info();
// 1 kim
// 5 choi
// 10 min

  • Person 클래스

    public class Person {
    	private String name
    	public Person(String name) {
    		this.name = name;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    }
  • Student 클래스

    public class Student extends Person{
    	public Student(String name) {
    		super(name);
    	}
    }
  • Alba 클래스

    public class Alba extends Student{
    	public Alba(String name) {
    		super(name);
    	}
    }
  • Seat 클래스

    public class Seat{
    	// Person, Student, Alba를 모두 저장할 수 있는 타입은 Person
    	private Person person;
    	// Seat 생성자를 생락하면
    	// public Seat() {}    -> 디폴트 생성자가 사용됨
    	// new Seat()를 이용한 시트 생성이 가능함
    	public Person getPerson() {
    		return person;
    	}
    	public void setPerson(Person person) {
    		this.person = person;
    	}
    }
  • Bus 클래스

    public class Bus {
    	private Seat[] seats;     // 배열 선언
    	private int limit;       // 버스 정원
    	// Bus 생성자에서 배열 생성을 진행함
    	public Bus(int cnt) {
    		seats = new Seat[cnt];       // 배열 생성, new Bus(25)인 경우 Seat가 25개 생성됨
    		limit = cnt;
    		for(int i = 0; i < cnt; i++) {
    			seats[i] = new Seat();
    		}
    	}
    	// ride() 메소드
    	public void ride(int seatNo, Person person) {
    		// 존재하지 않는 시트번호
    		if(seatNo <= 0 || seatNo > limit) {
    			return;     // ride() 메소드 종료
    		}
    		// 시트에 사람이 없으면, 시트번호에 탑승한 Person 저장하기
    		Seat seat = seats[seatNo - 1];
    		Person p = seat.getPerson();
    		if ( p == null) {
    			seat.setPerson(person);
    		}	
    	}
    	// info() 메소드
    	public void info() {
    		for (int i = 0; i < limit; i++) {     // limit은 seats 배열의 length와 같음
    			Seat seat = seats[i];
    			Person person = seat.getPerson();   //Person person = seats[i].getPerson();
    			if( person != null)   {  // if(seat.getPerson() != null), if(seats[i].getPerson())
    				System.out.println((i + 1) + "," + person.getName());
    				// System.out.println((i + 1) + "," + seat.getPerson().getName());
    				// System.out.println((i + 1) + "," + seats[i].getPerson.getName));
    			} else {
    				System.out.println((i + 1) + ", 비어 있음");
    			}
    		}	
    	}
    }
  • Main

    public class Main {
    	public static void main(String[] args) {
    	Bus bus = new Bus(25);
    	bus.ride(1 , new Person("kim"));
    	bus.ride(5 , new Student("choi"));
    	bus.ride(10 , new Alba("min"));
    	bus.info(); 
    	}
    }
  • 결과

-연습문제 ( 장보기 )

Snack, Meat, Milk는 모두 Product이다.
모든 Product은 이름(name)과 가격(price)만 가진다.
고객(Costomer)은 모든 Product을 10개 담을 수 있는 cart를 가진다.
고객은 돈(money)과 보너스포인트(bonusPoint, 구매액의 10%)를 가진다.

Customer customer = new Customer();
→ 아직 돈이 없는 고객
customer.setMoney(10000);
→ 10000원이 생긴 고객
customer.buy(new Snack("홈런볼", 1500));
→ 1500원 짜리 홈런볼을 산다. (카트에 담는다)
customer.buy(new Meat("한우", 5000));
→ 5000원 짜리 한우를 산다. (카트에 담는다)
customer.buy(new Milk("서울우유", 2500));
→ 2500원짜리 서울우유를 산다. (카트에담는다)
customer.reseipt;
→ 영수증을 본다.

/
홈런볼 1500원
한우 5000원
서울우유 2500원
----------------'
구매총액 9000원
보너스 900원
남은돈 1000원
/

  • Product 클래스

    public class Product {
    	private String name;
    	private int price;
    	public Product(String name, int price) {
    		this.name = name;
    		this.price = price;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getPrice() {
    		return price;
    	}
    	public void setPrice(int price) {
    		this.price = price;
    	}
    }
  • Snack 클래스

    public class Snack extends Product{
    	public Snack(String name, int price) {
    		super(name, price);
    	}
    }
  • Meat 클래스

    public class Meat extends Product {
    	public Meat(String name, int price) {
    		super(name, price);
    	}
    }
  • Milk 클래스

    public class Milk extends Product{
    	public Milk(String name, int price) {
    		super(name, price);
    	}
    }
  • Customer 클래스

    public class Customer {
    	private int money;
    	private int bonusPoint;
        private int total;
    	private Product[] cart = new Product[10];
    	private int idx;  // cart에 담긴 Product의 개수, cart 배열의 인덱스
    	// 생성자 생략
    	// new Customer() 가능
    	// 메소드 setMoney를 따로 만들지 않고 Getter Setter를 만든다
    	public int getMoney() {
    		return money;
    	}
    	public void setMoney(int money) {
    		this.money = money;
    	}
    	public int getBonusPoint() {
    		return bonusPoint;
    	}
    	public void setBonusPoint(int bonusPoint) {
    		this.bonusPoint = bonusPoint;
    	}
    	// buy() 메소드
    	public void buy ( Product product) {
    		int price = product.getPrice();
    		// 가진 돈보다 비싼 물건은 못 산다.
    		if(money < price) {
    			System.out.println("돈이 " + (price - money) + "원 부족합니다.");
    			return;
    		}
    		// 카트가 가득 차면 물건을 못 산다.  ( 현재 조건인 10개 보다 못산다.)
    		if (idx == cart.length) {
    			System.out.println("카트가 가득 찼습니다.");
    			return;
    		}
    		// 구매
    		cart[idx++] = product;   //cart[0]에 넣은 후 늘리는 후위연산
            total += price;
    		money -= price;
    		bonusPoint += price * 0.1;
    	}	
    	//receipt() 메소드
    	public void receipt() {
    		// 물건을 안 샀다.
    		if(idx == 0) {
    			System.out.println("구매한 물건이 없습니다.");
    			return;
    		}
    		// 구매 총액 구하기 및 출력하기
    		int total = 0;
    		for(int i = 0; i < idx; i++) {   
    			Product product = cart[i];
    			System.out.println(product.getName() + "\t" + product.getPrice() + "원");
    		}
    		System.out.println("-----------------------");
    		System.out.println("구매총액 " + total + "원");
    		System.out.println("보너스 " + bonusPoint + "원");
    		System.out.println("남은돈 " + money + "원");
    	}
    }
  • Main 클래스

    public class Main {
    	public static void main(String[] args) {
    		Customer customer = new Customer();			// 아직 돈이 없는 고객
    		customer.setMoney(10000);					// 10000원이 생긴 고객
    		customer.buy(new Snack("홈런볼", 1500));	    // 1500원짜리 홈런볼을 샀다. (카트에 담는다)
    		customer.buy(new Meat("한우", 5000));		// 5000원짜로 한우를 샀다. (카트에 담는다)
    		customer.buy(new Milk("서울우유", 2500));	// 2500원짜리 서울우유를 샀다. (카트에 담는다)
    		customer.buy(new Meat("불고기", 5000));		// 구매불가
    		customer.receipt();							// 영수증을 본다.
    	}
    }
  • 결과


다운캐스팅 (Down Casting)

  • 업캐스팅 된 서브 클래스 객체를 다시 서브클래스 타입으로 변환하는 것
  • 강제로 타입을 변환하는 casting 방식으로 처리해야 함
  • 업캐스팅의 문제를 해결하기 위한 또 다른 방법임

instanceof 연산자
-특정 인스턴스가 어떤 클래스타입인지 점검하는 연산자
-해당 클래스타입이면 true 반환, 아니면 false 반환

// 클래스타입 : Person
// 객체(인스턴스) : P
Person p = new Alba();        //업캐스팅
// p가 Student타입의 인스턴스이면 study() 메소드를 호출할 수 있다.
if(p instanceof Student) {
	((Student) p).study();    // 다운캐스팅
}
// P가 Alba타입의 인스턴스이면 work() 메소드를 호출할 수 있다.
if(p instanceof Alba) {
	((Alba) p).work();       // 다운캐스팅
}
// 결과
// 공부한다.

-연습문제

Car : drive()
Ev : drive() , charge()
Hybrid : drive() , charge(), addOil()
Main : 임의의 자동차 10대 배열에 저장하기 (33% 확률로 랜덤 생성)
Car이면 drive()호출
Ev이면 charge()호출
Hybrid이면 addOil()호출

  • Car 클래스

    public class Car {
    	public void drive() {
    		System.out.println("운전한다.");
    	}
    }
  • Ev 클래스

    public class Ev extends Car{
    	public void charge() {
    		System.out.println("충전한다.");
    	}
    }
  • Hybrid 클래스

    public class Hybrid extends Ev{
    	public void addOil() {
    		System.out.println("기름을 넣는다.");
    	}
    }
  • Main 클래스

    public class Main {
    	public static void main(String[] args) {
        	Car[] cars = new Car[10];
            for (int i = 0; i <cars.length; i++) {
            	if(Math.random() < 0.33) {
                	cars[i] = new Car();
                } else if(Math.random() < 0.66) {
                	cars[i] = new Ev();
                } else {
                	cars[i] = new Hybrid();
                	}
             	}
            for ( int i = 0; i < cars.length; i++) {
            	if(cars[i] instanceof Hybrid) {
                	((Hybrid) cars[i]).addOil();
                } else if ( cars[i] instanceof Ev) {
                	((Ev) cars[i]).charge();
                } else if ( cars[i] instanceof Car) {
                	cars[i].drive();
                }
            }
    }
    // 상속관계의 instance 체크는 서브클래스부터 체크해줘야함
profile
응애 나 애기 개발자

0개의 댓글