자바의정석

자바의 정석 7장 연습문제 (1~19)

유호야 2022. 3. 31. 19:33
반응형

내가 쓴 답

class SutdaDeck {
	final int CARD_NUM = 20;
	SutdaCard[] cards = new SutdaCard[CARD_NUM];

	SutdaDeck() {
		for(int i = 0; i < CARD_NUM; i++) {
			if(i < 10) {
				cards[i].num = i+1;
				if(i == 1 || i == 3 || i == 8)
					cards[i].isKwang = true;
			} else {
				cards[i].num = i-9;
			}
			
		}
	}
}

 

하지만 더 간결하게 작성할 수 있었다

SutdaDeck() {
	for(int i = 0; i < CARD_NUM; i++) {
		cards[i].num = i%10 + 1;
		cards[i].isKwang = ((i < 10) && (i == 1 || i == 3 || i == 8)) ? true : false;
	}
}

 

해설에서는 int num = 을 따로 생성하고 
cards[i] = new SutdaCard(num,isKwang); 으로 한 번에 집어 넣었다.

SutdaDeck() {
    for(int i=0;i < cards.length;i++) {
        int num = i%10+1;
        boolean isKwang = (i < 10)&&(num==1||num==3||num==8);
        cards[i] = new SutdaCard(num,isKwang);
    }
}

 


shuffle() 메서드는 로또에서 숫자 섞기 처럼 했는데
그것도 맞지 않을까... (?)

나머지 하나는 유효성 검사 처리와, 고정값 20을 주지 않고, cards.length을 줘야하는 것 

void shuffle() {
		//배열 cards에 담긴 카드의 위치 섞기 
		for(int i = 0; i < cards.length; i++) {
			int j = (int)(Math.random()*cards.length);
			SutdaCard tmp = cards[i];
			cards[i] = cards[j];
			cards[j]= tmp;
		}
	}
	
	SutdaCard pick(int index) {
		if(index < 0 || index >20)
			return null;
		return cards[index];
	}
	
	SutdaCard pick () {
		int random = (int)(Math.random()*cards.length);
		return cards[random];
	}

 



 

오버로딩과 오버라이딩은 완전히 다르지만 왜 헷갈리느냐...

다시 정리해보자면

오버라이딩은 덮어쓰기 
조상 클래스에서 정의된 메서드를 자손 클래스에 맞게 변경하는 것이다 
새로운 메서드가 아니라서, 이름, 매개변수, 반환 타입 모두 일치해야 한다. 


즉 자손 클래스에서 인스턴스를 생성할 때 기본 생성자인 Tv()가 호출되고 Tv()는 조상생성자 super()를 호출한다는 것 

super();  // 이 부분이 생략되어 있는 것이다. 

따라서 super() 를 추가하거나

class Product {
	int price; // 제품의 가격
	int bonusPoint; // 제품구매 시 제공하는 보너스점수

	Product(int price) {
		this.price = price;
		bonusPoint = (int) (price / 10.0);
	}
}

class Tv extends Product {
	Tv() {
		super(1);
	}

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

class Exercise7_5 {
	public static void main(String[] args) {
		Tv t = new Tv();
	}
}

tv() 생성자 부분에 super(1); 과 같이 product의 생성자 형식에 맞춰주면 에러가 사라진다. 


조상에 정의된 인스턴스 변수들이 초기화되도록 하기 위해서 


Parent 클래스에 정의된 x의 값 = 200 

Child 클래스의 정의된 x의 값 = 1000

그러나 c.getX(); 여기서 getX는 parent에 정의된 메서드이기 때문에 
parent 클래스에 존재하는 x의 값이 메서드에 적용되어 출력이 된다. 

따라서 200 ... 

조상 클래스의 멤버들을 상속을 받은 자손 클래스는 그 역시 독립적으로 존재하는 줄 알았으나, 그것이 아니라 새로 정의하지 않을 경우에 조상 클래스 내의 인스턴스 변수들과 연결되어 있다.... 


default는 같은 패키지 내에서만

protected는 같은 패키지 내에서 그리고 다른 패키지의 자손 클래스에서 접근 가능 


메서드에 final을 붙이면 오버라이딩 할 수 없다 (오버로딩 아님)


void setIsPowerOn(boolean isPowerOn) {
		this.isPowerOn = isPowerOn;
	}
	
	boolean getIsPowerOn() {
		return isPowerOn;
	}
	
	void setChannel(int channel) {
		if(!(channel < MIN_CHANNEL|| channel > MAX_CHANNEL))
			this.channel = channel;
	}
	
	int getChannel() {
		return channel;
	}
	
	void setVolume(int volume) {
		if(!(volume < MIN_VOLUME || channel > MAX_VOLUME))
			this.volume = volume;
	}
	
	int getVolume() {
		return volume;
	}

유효성 검사 !


public void gotoPrevChannel() {
	if(channel != MIN_CHANNEL) {
		channel -= 1;
	} else {
		channel = MAX_CHANNEL;
	}
}

prevChannel = this.channel;

이부분이 엄청 헷갈렸는데 생각해보니 1번에서 10번으로 채널을 변경한다고 치면
10번을 누르는 순간 setChannel 메서드가 실행이 되면서, 
기존의 채널이었던 1번을 prevChannel에 저장을 하고, 현재 channel값에 10을 넣는다. 따라서 중간에 
prevChannel은 한 번 이상 채널을 바꾸었을 때 prevChannel값이 존재할 수 있게 되는 것이다.


접근 제어자가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자
지역변수는 아니다. 


Math 클래스의 모든 메서드가 static 메서드이고, 인스턴스 변수가 존재하지 않기 때문에 객체를 생성할 필요가 없기 때문이다. 

 


class SutdaCard2 {
	final int NUM;
	final boolean IS_KWANG;

	SutdaCard2() {
		this(1, true);
	}

	SutdaCard2(int num, boolean isKwang) {
		this.NUM = num;
		this.IS_KWANG = isKwang;
	}

	public String toString() {
		return NUM + (IS_KWANG ? "K" : "");
	}
}

class Exercise7_14 {
	public static void main(String args[]) {
		SutdaCard2 card = new SutdaCard2(1, true);
	}
}

 

 


※ 조상타입의 인스턴스를 자손타입으로 형변환 할 수 없다

조상타입의 인스턴스를 자손타입으로 형변환할 수 없다.... 
명시하면 되는 줄 알았다 


 


기계마다 움직이는 정도가 다르기 때문에 해당 메서드 부분을 추상 abstract 메서드로 남겨둔다.

abstract class Unit2 {
	int x, y;
	abstract void move(int x, int y);
	void stop() {}
}

class Marine extends Unit2{
	void stimPack() {}
	void move(int x, int y) {}
}

class Tank extends Unit2{
	void move(int x, int y) {}
	void changeMode() {}

}

class Dropship extends Unit2 {
	void move(int x, int y) {}
	void load() {}
	void unload() {}
}

public class Exercise7_15 {

}

 


 

 

 

내 답

public static void action(Robot r) {
	if(r instanceof DanceRobot) {
		((DanceRobot) r).dance();
	} else if(r instanceof SingRobot) {
		((SingRobot) r).sing();
	} else {
		((DrawRobot) r).draw();
	}
 }

 

객체를 새로 생성해서 메서드를 호출함 


 

toString 값이 null이 아니면... 때문에 계속 오류 떴다... 그냥 
cart[i] 값이 null이 아니면 했으면 되는 건데 ㅋㅋ

if(cart[i].toString() != null) {
    list += cart[i].toString() + " ";
}

import java.util.Arrays;

public class Exercise7_19 {

	public static void main(String[] args) {
		
		Buyer b = new Buyer();
		b.buy(new Tv2());
		b.buy(new Computer());
		b.buy(new Tv2());
		b.buy(new Audio());
//		b.buy(new Computer());
//		b.buy(new Computer());
//		b.buy(new Computer());
		b.summary();
	}

}

class Buyer {
	int money = 1000;
	Product2[] cart = new Product2[3];
	int i = 0;

	void buy(Product2 p) {
		
		if(money < p.price) { // 물건의 가격이 가진 돈 보다 큰 경우
			return;
		} else {
			add(p);
			money -= p.price;
		}
	}

	void add(Product2 p) {
		for(int i = 0; i < cart.length; i++) {
			if(cart[i] == null) {
				cart[i] = p;
				System.out.println("add: "+cart[i]);
				return;
			}
		}
		
		//카트의 길이가 부족한 경우 복사
		Product2[] cart2 = new Product2[cart.length*2];
		for(int i = 0; i < cart.length; i++) {
			cart2[i] = cart[i];
		}
		
		cart = new Product2[cart.length*2];
		for(int i = 0; i < cart2.length; i++) {
			cart[i] = cart2[i];
		}

		add(p);
		
	}

	void summary() {
		String list = "";
		int sum = 0;
		

		for(int i = 0; i < cart.length; i++) {
			if(cart[i] != null) {
				sum += cart[i].price;
				list += cart[i].toString() +" ";
			}
		}
		System.out.println("구입한 물건: " + list);
		System.out.println("총 사용 금액: " + sum);
		System.out.println("남은 금액: " + money);
	}
}

class Product2 {
	int price;

	Product2(int price) {
		this.price = price;
	}
}

class Tv2 extends Product2 {
	Tv2() {
		super(100);
	}

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

class Computer extends Product2 {
	Computer() {
		super(200);
	}

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

class Audio extends Product2 {
	Audio() {
		super(50);
	}

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

 

 

배열의 복사하는 방법 arraycopy를 이용했다. 
그리고 i 값을 늘리면서 cart 길이보다 클 때 cart[i++] = p; 로 배열에 추가

잔액이 부족할 때 잔액이 부족해서 구매할 수 없음을 알린다.


 

반응형