서노썬
sun noes sun
서노썬
전체 방문자
오늘
어제
  • 카테고리 (142)
    • Java (89)
      • Day1 (20)
      • Day2 (16)
      • Day3 (4)
      • Day4 (5)
      • Day5 (2)
      • Day6 (2)
      • Day7 (4)
      • Day8 (6)
      • Day9 (3)
      • Day10 (0)
      • Day11 (0)
      • Day12 (0)
      • Day13 (3)
      • Day14 (0)
      • Day15 (0)
      • Day16 (0)
      • Day19 (0)
      • Day20 (0)
      • Day21 (2)
      • Day22 (4)
      • Day23 (2)
      • Day24 (5)
      • Day25 (4)
      • Day27 (2)
      • Day28 (3)
      • Day29 (1)
      • Day30 (1)
      • Day31 (0)
      • Day32 (0)
      • Dat33 (0)
      • Day34 (0)
      • Day35 (0)
      • Day36 (0)
    • HTML (37)
      • Day36 (20)
      • Day37 (3)
      • Day38 (2)
      • Day39 (8)
      • Day40 (3)
    • SQL (4)
      • Day40 (4)
      • Day41 (0)
      • Day42 (0)
      • Day43 (0)
      • Day44 (0)
      • Day45 (0)
    • JSP (0)
      • Day46 (0)
      • Day75 (0)
    • PYTHON (0)
      • Day75 (0)
      • Day76 (0)
    • Photo (12)

블로그 메뉴

  • 홈
  • 방명록

인기 글

최근 글

태그

  • java메뉴입력
  • 자바자료형
  • Java
  • 자바break
  • 자바continue
  • 논리연산자
  • java자료형
  • java데이터타입
  • 자바연산자
  • 자바

티스토리

hELLO · Designed By 정상우.
서노썬

sun noes sun

Java/Day23

[Java] 자바의 정석 Chapter7. 객체지향 프로그래밍2 - 연습문제

2021. 11. 29. 22:45

[ 자바의 정석 Chapter7. 객체지향 프로그래밍2 - 연습문제 ]

 

7-1. 섯다카드 20장을 포함하는 섯다카드 한 벌(SutdaDeck클래스)을 정의한 것이다. 섯다카드 20장을 담는 SutdaCard배열을 초기화하시오.

단, 섯다카드는 1부터 10까지의 숫자가 적힌 카드가 한 쌍씩 있고, 숫자가 1, 3, 8인 경우에는 줄 중의 한 장은 광(Kwang)이어야한다. 즉, SutdaCard의 인스턴스변수 isKwang의 값이 true이어야한다.

 

class SutdaDeck
{
	final int CARD_NUM = 20;
	SutdaCard[] cards = new SutdaCard[CARD_NUM];
	SutdaDeck()
	{
		/*
			(1) 배열 SutdaCard를 적절히 초기화 하시오.
		*/
	}
}
class SutdaCard
{
	int num;
	boolean isKwang;

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

	SutdaCard(int num, boolean isKwang)
	{
		this.num = num;
		this.isKwang = isKwang;
	}

	// info()대신 Object클래스의 toString()을 오버라이딩했다.
	public String toString()
	{
		return num + ( isKwang ? "K":"");
	}
}

class Exercise7_1
{
	public static void main(String args[])
	{
		SutdaDeck deck = new SutdaDeck();
		for(int i=0; i<deck.cards.length; i++)
		System.out.print(deck.cards[i]+",");
	}
}

 

- 출력결과

1K, 2, 3K, 4, 5, 6, 7, 8k, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

 

☞

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);
}

 

 

7-2. 문제 7-1의 SutdaDeck클래스에 다음에 정의된 새로운 메서드를 추가하고 테스트 하시오.
[주의] Math.random().을 사용하는 경우 실행결과와 다를 수 있음.

1.
메서드명 : shuffle
기능 : cards에 담긴 카드의 위치를 뒤섞는다.(Math.random()사용)
반환타입 : 없음
매개변수 : 없음

2.
메서드명 : pick
기능: 배열 cards에서 지정된 위치의 SutdaCard를 반환한다.
반환타입 : SutdaCard
매개변수 : int index - 위치

3.
메서드명 : pick
기능 : 배열 cards에서 임의의 위치의 SutdaCard를 반환한다.(Math.random()사용)
반환타입 : SutdaCard
매개변수 : 없음

 

class SutdaDeck
{
	final int CARD_NUM = 20;
	SutdaCard[] cards = new SutdaCard[CARD_NUM];
	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);
		}
	}
	/*
		(1) 위에 정의된 세 개의 메서드를 작성하시오.
	*/
}
class SutdaCard
{
	int num;
	boolean isKwang;

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

	SutdaCard(int num, boolean isKwang)
	{
		this.num = num;
		this.isKwang = isKwang;
	}

	public String toString()
	{
		return num + ( isKwang ? "K":"");
	}
}

class Exercise7_2
{
	public static void main(String args[])
	{
		SutdaDeck deck = new SutdaDeck();

		System.out.println(deck.pick(0));
		System.out.println(deck.pick());
		deck.shuffle();

		for(int i=0; i < deck.cards.length;i++)
			System.out.print(deck.cards[i]+",");

		System.out.println();
		System.out.println(deck.pick(0));
	}
}

 

- 실행결과

1K
7
2, 6, 10, 1K, 7, 3, 10, 5, 7, 8, 5, 1, 2, 9, 6, 9, 4, 8K, 4, 3K,
2

 

☞

void shuffle
{
	int temp=0;
	
	for(int i=0; i<cards.length; i++)
	{
		int j = (int)(Math.random() * cards.length);

		SutdaCard temp = cards[i];
		cards[i] = cards[j];
		cards[j] = temp;
	}
}

SutdaCard pick(int idx)
{
	if(idx<0 || idx>= CARD_NUM)
	{
		return null;
	}
	return cards[idx];
}

SutdaCard pick()
{
	int idx = (int)(Math.random() * cards.length);
	return pick(idx);
}

 

 

7-3. 오버라이딩의 정의와 필요성에 대해서 설명하시오.

- 정의 : 상위 클래스에게 상속받은 메소드를 하위 클래스에서 사용할 수 있도록 구현하는 것

- 필요성 : 상위 크래스에게 상속받은 메소드를 하위 클래스에서 사용하기 위한 재정의

 

 

7-4. 다음 중 오버라이딩의 조건으로 옳지 않은 것은? (모두 고르시오)

a. 조상의 메서드와 이름이 같아야 한다.
b. 매개변수의 수와 타입이 모두 같아야 한다.
c. 접근 제어자는 조상의 메서드보다 좁은 범위로만 변경할 수 있다.
d. 조상의 메서드보다 더 많은 수의 예외를 선언할 수 있다.

 

☞

c : 접근 제어자는 조상의 메소드보다 동일하거나 더 넓은 범위로만 변경할 수 있다.

d : 조상의 메소드보다 더 많은 수의 예외를 선언할 수 없다.

 

 

7-5. 다음의 코드는 컴파일하면 에러가 발생한다. 그 이유를 설명하고 에러를 수정하기 위해서는 코드를 어떻게 바꿔야 하는가?

class Product
{
	int price;
	int bonusPoint;

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

class Tv extends Product
{
	Tv() {}

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

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

 

☞ product 클래스에 기본 생성자 product()가 없기 때문에 에러가 발생한다. 

class Product
{
	int price;
	int bonusPoint;

	product() {}

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

class Tv extends Product
{
	Tv() {}

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

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

 

 

7-6. 자손 클래스의 생성자에서 조상 클래스의 생성자를 호출해야 하는 이유는 무엇인가?

 

☞ 자손 클래스에서 인스턴스를 생성하면 조상 클래스에서 상속받은 인스턴스 변수들도 자손 클래스에서 생성되는데 이 때 조상 클래스에서 상속받은 변수들도 초기화를 해줘야 하기 때문에

 

 

7-7. 다음 코드를 실행했을 때 호출되는 생성자의 순서와 실행결과를 적으시오.

class Parent
{
	int x=100;

	Parent()
	{
		this(200);
	}
	Parent(int x)
	{
		this.x=x;
	}
	int getX()
	{
		return x;
	}
}

class Child extends Parent
{
	int x=3000;

	Child()
	{
		this(1000);
	}
	Child(int x)
	{
		this.x=x;
	}
}

class Exercise7_7
{
	public static void main(String[] args)
	{
		Child c = new Child();

		System.out.println("x=" + c.getX());
	}

 

☞ Child() - Child(int x) - Parent() - Parent(int x) - Objext() / x=200

 

 

7-8. 다음 중 접근제어자를 접근범위가 넓은 것에서 좁은 것의 순으로 바르게 나열한 것은?

a. public-protected-(default)-private
b. public-(default)-protected-private
c. (default)-public-protected-private
d.private-protected-(default)-public

 

☞ a. public-protected-(default)-private

 

 

7-9. 다음 중 제어자 fianl을 붙일 수 있는 대상과 붙였을 떄 그 의미를 적은 것이다. 옳지 않은 것은? (모두 고르시오)

a. 지역변수 - 값을 변경할 수 없다.
b. 클래스 - 상속을 통해 클래스에 새로운 멤버를 추가할 수 없다.
c. 메서드 - 오버로딩을 할 수 없다.
d. 멤버변수 - 값을 변경할 수 없다.

☞ c. 메서드 - 오버로딩이 아닌 오버라이딩을 할 수 없다.

 

 

7-10. MyTv2클래스의 멤버변수 isPowerOn, channel, volume을 클래스 외부에서 접근할 수 없도록 제어자를 붙이고
대신 이 멤버변수들의 값을 어디서나 읽고 변경할 수 있도록 getter와 setter메서드를 추가하라.

 

class MyTv2
{
	boolean isPowerOn;
	int channel;
	int volume;

	final int MAX_VOLUME = 100;
	final int MIN_VOLUME = 0;
	final int MAX_CHANNEL = 100;
	final int MIN_CHANNEL = 0;

	/*
		(1) 알맞은 코드를 넣어 완성하시오.
	*/
}

class Exercise7_10
{
	public static void main(String[] args)
	{
		MyTv2 t= new MyTv2();

		t.setChannel(10);
		System.out.println("CH : " + t.getChannel());
		t.setVolume(20);
		System.out.println("VOL : " + t.getVolume());
	}
}

 

- 실행결과
CH : 10
VOL : 20

 

☞

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

 

 

7-11. 문제 7-10에서 작성한 MyTv2 클래스에 이전 채널(previous channel)로 이동하는 기능의 메서드를 추가해서
실행결과와 같은 결과를 얻도록 하시오.[Hint] 이전 채널의 값을 저장할 멤버변수를 정의하라.

메서드명 : gotoPrevChannel
기능 : 현재 채널을 이전 채널로 변경한다.
반환타입 : 없음
매개변수 : 없음

 

class MyTv2
{
	boolean isPowerOn;
	int channel;
	int volume;

	final int MAX_VOLUME = 100;
	final int MIN_VOLUME = 0;
	final int MAX_CHANNEL = 100;
	final int MIN_CHANNEL = 0;

	/*
		(1) 문제 7-10의 MyTv클래스에 gotoPrevChannel메서드를 추가하여 완성하시오.
	*/
}

class Exercise7_11
{
	public static void main(String[] args)
	{
		MyTv2 t = new MyTv2();

		t.setChannel(10);
		System.out.println("CH : " + t.getChannel());
		t.setVolume(20);
		System.out.println("VOL : " + t.getVolume());
		t.gotoPrevChannel();
		System.out.println("CH : " + t.getChannel());
		t.gotoPrevChannel();
		System.out.println("CH : " + t.getChannel());
	}
}

- 출력결과
CH : 10
CH : 20
CH : 10
CH : 20

 

☞ 

class MyTv2
{
	boolean isPowerOn;
	int channel;
	int volume;
	int prevChannel;

	final int MAX_VOLUME = 100;
	final int MIN_VOLUME = 0;
	final int MAX_CHANNEL = 100;
	final int MIN_CHANNEL = 1;

	public int getChannel()
	{
		return channel;
	}
	public void setChannel(int channel)
	{
		if(channel<MIN_CHANNEL || channel>MAX_CHANNEL)
		{
			return;
		}
		prevChannel = this.channel;
		this.channel = channel;
	}
	public int getVolume()
	{
		return volume;
	}
	public void setVolume(int volume)
	{
		if(volume<MIN_VOLUME || volume>MAX_VOLUME)
		{
			return;
		}
		this.volume = volume;
	}
	gotoPrevChannel()
	{
		setChannel(prevChannel);
	}
}

class Exercise7_11
{
	public static void main(String[] args)
	{
		MyTv2 t = new MyTv2();

		t.setChannel(10);
		System.out.println("CH : " + t.getChannel());
		t.setVolume(20);
		System.out.println("VOL : " + t.getVolume());
		t.gotoPrevChannel();
		System.out.println("CH : " + t.getChannel());
		t.gotoPrevChannel();
		System.out.println("CH : " + t.getChannel());
	}
}

 

 

 

7-12. 다음 중 접근 제어자에 대한 설명으로 옳지 않은 것은? (모두 고르시오)

a. public은 접근제한이 전혀 없는 제어자이다.
b. (default)가 붙으면, 같은 패키지 내에서만 접근이 가능하다.
c. 지역변수에도 접근 제어자를 사용할 수 있다.
d. protected가 붙으면, 같은 패키지 내에서도 접근이 가능하다.
e. protected가 붙으면, 다른 패키지의 자손 클래스에서 접근이 가능하다.

 

☞ c. 지역변수가 아닌 클래스, 멤버변수, 메소드, 생성자에서 접근 제어자를 사용할 수 있다.


7-13. Math클래스의 생성자는 접근 제어자가 private이다. 그 이유는 무엇인가?

Math클래스에 들어가는 메소드는 모두 static 메소드이고, 인스턴스 변수가 존재하지 않기 때문에

 

 

7-14. 문제 7-1에 나오는 섯다카드의 숫자와 종류(isKwang)는 사실 한 번 값이 지정되면 변경되어서는 안되는 값이다.
카드의 숫자가 한 번 잘못 바뀌면 똑같은 카드가 두 장이 될 수도 있기 때문이다. 이러한 문제점이 발생하지 않도록 아래의 SutdaCard를 수정하시오.

 

class SutdaCard
{
	int num;
	boolean isKwang;

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

	SutdaCard(int num, boolean isKwang)
	{
		this.num = num;
		this.isKwang = isKwang;
	}

	public String toString()
	{
		return num + ( isKwang ? "K":"");
	}
}

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

 

☞

int num > final int NUM
boolean isKwang > final boolean IS_KWANG

으로 모두 바꿔주기

 

 

7-15. 클래스가 다음과 같이 정의되어 있을 때, 형변환을 올바르게 하지 않은 것은? (모두 고르시오)

class Unit{}
class AirUnit extends Unit{}
class GroundUnit extends Unit{}
class Tank extends GroundUnit{}
class AirCraft extends AirUnit{}

Unit u = new GroundUnit();
Tank t = new Tank();
AirCraft ac = new AirCraft();

a. u = (Unit)ac;
b. u = ac;
c. GroundUnit gu = (GroundUnit)u;
d. AirUnit au = ac;
e. t = (Tank)u;
f. GroundUnit gu = t;

☞ e. t = (Tank)u; / 조상타입의 인스턴스를 자손 타입으로 형변환 할 수 없다.

 

 

 

7-16. 다음 중 연산결과가 true가 아닌 것은? (모두 고르시오)

class Car{}
class FireEngine extends Car implements Movable{}
class Ambulance extends Car {}

FireEngine fe = new FireEngine();

a. fe instanceof FireEngine
b. fe instanceof Moavable
c. fe instanceof Object
d. fe instanceof Car
e. fe instanceof Ambulance

☞ e. fe instanceof Ambulance / instanceof 연산자는 object나 구현한 인터페이스에 대해서 true를 반환한다.


7-17. 아래 세 개의 클래스로부터 공톤부분을 뽑아서 Unit이라는 클래스를 만들고, 이 클래스를 상속하도록 코드를 변경하시오.

calss Marine
{
	int x, y;
	void move(int x, int y)	{ /* 지정된 위치로 이동 */ }
	void stop()		{ /* 현재 위치에 정지 */ }
	void stimPack()		{ /* 스팀팩을 사용한다 */}
}

class Tank
{
	int x, y;
	void move(int x, int y)	{ /* 지정된 위치로 이동 */ }
	void stop()		{ /* 현재 위치에 정지 */ }
	void changeMode()	{ /* 공격모드를 변환한다 */}
}

class Dropship
{
	int x, y;
	void move(int x, int y)	{ /* 지정된 위치로 이동 */ }
	void stop()		{ /* 현재 위치에 정지 */ }
	void load()		{ /* 선택된 대상을 태운다 */ }
	void unload()		{ /* 선택된 대상을 내린다 */ }
}

 

☞

abstract class Unit
{
	int x, y;
	abstract void move(int x, int y);
	void stop(){}
}
calss Marine extends Unit
{
	void move(int x, int y) {}
	void stimPack()		{ /* 스팀팩을 사용한다 */}
}

class Tank extends Unit
{
	void move(int x, int y) {}
	void changeMode()	{ /* 공격모드를 변환한다 */}
}

class Dropship extends Unit
{
	void move(int x, int y) {}
	void load()		{ /* 선택된 대상을 태운다 */ }
	void unload()		{ /* 선택된 대상을 내린다 */ }
}



7-18. 다음과 같은 실행결과를 얻도록 코드를 완성하시오.
[Hint] instanceof 연산자를 사용해서 형변환한다.

메서드명 : action
기능 : 주어진 객체의 메서드를 호출한다.
        DanceRobot인 경우, dance()를 호출하고,
        SingRobot인 경우, sing()을 호출하고,
        DrawRobot인 경우, draw()를 호출한다.
반환타입 : 없음
매개변수 : Robot r - Robot인스턴스 또는 RObot의 자손 인스턴스

 

class Exercise7_18
{
	/*
		(1) action . 메서드를 작성하시오
	*/

	public static void main(String[] args)
	{
		Robot[] arr = { new DanceRobot(), new SingRobot(), new DrawRobot()};
		for(int i=0; i< arr.length;i++)
		action(arr[i]);
	}
}

class Robot {}

class DanceRobot extends Robot
{
	void dance()
	{
		System.out.println(" ."); 춤을 춥니다
	}
}

class SingRobot extends Robot
{
	void sing()
	{
		System.out.println(" ."); 노래를 합니다
	}
}

class DrawRobot extends Robot
{
	void draw()
	{
		System.out.println(" ."); 그림을 그립니다
	}
}

 

- 출력결과
춤을 춥니다.
노래를 합니다.
그림을 그립니다.

☞

class Exercise7_18
{
	static void action(RObotr)
	{
		if(r instancf DanceRobot)
		{
			((DanceRobot) r).dance();
		}
		else if(r instance of SingRobot)
		{
			((SingRobot) r). sing();
		}
		else
		{
			((DrawRobot) r). draw();
		}
	}
}

	public static void main(String[] args)
	{
		Robot[] arr = { new DanceRobot(), new SingRobot(), new DrawRobot()};
		for(int i=0; i< arr.length;i++)
		action(arr[i]);
	}
}

class Robot {}

class DanceRobot extends Robot
{
	void dance()
	{
		System.out.println(" ."); 춤을 춥니다
	}
}

class SingRobot extends Robot
{
	void sing()
	{
		System.out.println(" ."); 노래를 합니다
	}
}

class DrawRobot extends Robot
{
	void draw()
	{
		System.out.println(" ."); 그림을 그립니다
	}
}

 

 

7-19. 다음은 물건을 구입하는 사람을 정의한 Buyer 클래스이다. 이 클래스는 멤버변수로 돈(money)과 장바구니(cart)를 가지고 있다.


제품을 구입하는 기능의 buy메서드와 장바구니에 구입한 물건을 추가하는 add메서드, 구입한 물건의 목록과 사용금액,
그리고 남은 금액을 출력하는 summary메서드를 완성하시오.

1.
- 메서드명 : buy
- 기능 : 지정된 물건을 구입한다. 가진 돈(money)에서 물건의 가격을 빼고, 장바구니(cart)에 담는다. 만일 가진 돈이 물건의 가격보다 적다면 바로 종료한다.
- 반환타입 : 없음
- 매개변수 : Product p - 구입할 물건

2.
- 메서드명 : add
- 기능 : 지정된 물건을 장바구니에 담는다. 만일 장바구니에 담을 공간이 없으면 장바구니의 크기를 2배로 늘린 다음에 담는다.
- 반환타입 : 없음
- 매개변수 : Product p - 구입할 물건

3.
- 메서드명 : summary
- 기능 : 구입한 물건의 목록과 사용금액, 남은 금액을 출력한다.
- 반환타입 : 없음
- 매개변수 : 없음

 

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

class Buyer
{
	int money = 1000;
	Product[] cart = new Product[3]; // 구입한 제품을 저장하기 위한 배열
	int i = 0; // Product cart index 배열 에 사용될

	void buy(Product p)
	{
		/*
		(1) 아래의 로직에 맞게 코드를 작성하시오
		1.1 가진 돈과 물건의 가격을 비교해서 가진 돈이 적으면 메서드를 종료한다
		1.2 가진 돈이 충분하면 제품의 가격을 가진 돈에서 빼고,
		1.3 장바구니에 구입한 물건을 담는다. (add 메서드 호출)
		*/
	}

	void add(Product p)
	{
		/*
		(2)  아래의 로직에 맞게 코드를 작성하시오
		1.1   i의 값이 장바구니의 크기보다 같거나 크면
		  1.1.1 기존의 장바구니보다 2배 큰 새로운 배열을 생성한다
		  1.1.2 기존의 장바구니의 내용을 새로운 배열에 복사한다
		  1.1.3 새로운 장바구니와 기존의 장바구니를 바꾼다
		1.2  물건을 장바구니(cart) 에 저장한다 그리고 i의 값을 1 증가시킨다
		*/
	} // add(Product p)

	void summary()
	{
		/*
			(3) 아래의 로직에 맞게 코드를 작성하시오
			1.1 장바구니에 담긴 물건들의 목록을 만들어 출력한다
			1.2 장바구니에 담긴 물건들의 가격을 모두 더해서 출력한다
			1.3 물건을 사고 남은 금액(money)를 출력한다
		*/
	} // summary()
}

class Product
{
	int price; // 제품의 가격
	Product(int price)
	{
		this.price = price;
	}
}

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"; }
}

 

☞ (참고) 문자열과 참조변수의 덧셈(결합연산)은 참조변수에 toString()을 호출해서 문자열을 얻어 결합한다. 그래서 문제 7-19에 나오는 cart[i] + "," 는 cart[i].toString()이 되고, 만일 p.toString()의 결과가 "Audio"라면 "Audio ,"가 된다.

 

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

class Buyer
{
	int money = 1000;
	Product[] cart = new Product[3];
	int i = 0; // Product cart index 배열 에 사용될

	void buy(Product p)
	{
		if(money < p.price)
		{
			System.out.println("잔액이 부족하여 " + p + "을/를 살 수 없습니다.");
			return;
		}
		money -= p.price;
		add(p);
	}

	void add(Product p)
	{
		if(i >= cart.length)
		{
			Prodauct[] tmp = new Prioduct[cart.length*2];
			System.arraycopy(cart, 0, tmp, 0, cart.length);
			cart = tmp;
		}
		cart[i++] = p;	
	}

	void summary()
	{
		Sting itemList = "";
		int sum = 0;

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

class Product
{
	int price;
	Product(int price)
	{
		this.price = price;
	}
}

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"; }
}

 

 

7-20. 다음의 코드를 실행한 결과를 적으시오.

class Exercise7_20
{
	public static void main(String[] args)
	{
		Parent p = new Child();
		Child c = new Chile();
	
		System.out.println("p.x= " + p.x);
		p.method();	

		System.out.println("c.x= " + c.x);
		c.method();
	}
}

class Parent
{
	int x = 100;

	void method()
	{
		System.out.println("Parent Method");
	}
}

class Chile extends Parent
{
	int x = 200;

 	void method()
	{
		System.out.println("Child Method");
	}
}

 

☞
p.x = 100
Child Method
c.x = 200
Child Method


7-21. 다음과 같이 attack 메서드가 정의되어 있을 때, 이 메서드의 매개변수로 가능한 것 두 가지를 적으시오.

interFace Mavable
{
	void move(int x, int y);
}

void attack(Movable f)
{
	/* 내용 생략 */
}

☞ null , Movable 인터페이스를 구현한 클래스나 그 자손의 인스턴스


7-22. 아래는 도형을 정의한 Shape 클래스이다. 이 클래스를 조상으로 하는 Circle 클래스와 Rectangle 클래스를 작성하시오.

 

이 때, 생성자도 각 클래스에 맞게 적절히 추가해야 한다.

(1)
클래스명 : Circle
조상클래스 : Shape
멤버변수 : double r - 반지름

(2)
클래스명 : Rectangle
조상클래스 : Shape
멤버변수 : double width - 폭 / double height - 높이
메서드 :
1. 메서드명 : isSquare
   기능 : 정사각형인지 아닌지를 알려준다.
   반환타입 : boolean
   매개변수 : 없음

 

abstract class Shape
{
	Point p;

	Shape()
	{
		this(new Point(0,0));
	}
	Shape(Point p)
	{
		this.p = p;
	}

	abstract double calcArea(); // 도형의 면적을 계산해서 반환하는 메서드
	
	Point getPosition()
	{
		return p;
	}
	void setPosition(Point p)
	{
		this.p = p;
	}
}
class Point
{
	int x;
	int y;

	Point()
	{
		this(0,0);
	}

	Point(int x, int y)
	{
		this.x=x;
		this.y=y;
	}

	public String toString()
	{
		return "["+x+","+y+"]";
	}
}

 

☞

abstract class Shape
{
	Point p;

	Shape()
	{
		this(new Point(0,0));
	}
	Shape(Point p)
	{
		this.p = p;
	}

	abstract double calcArea(); // 도형의 면적을 계산해서 반환하는 메서드
	
	Point getPosition()
	{
		return p;
	}
	void setPosition(Point p)
	{
		this.p = p;
	}
}

class Rectangle extends Shape
{
	double width;
	double height;

	Rectangle(double width, double height)
	{
		this(new Point(0,0), width, height);
	}

	Rectangle(Point p, double width, double height)
	{
		super(p); // . 조상의 멤버는 조상의 생성자가 초기화하도록 한다
		this.width = width;
		this.height = height;
	}

	boolean isSquare()
	{
		// width height 0 width height true . 나 가 이 아니고 와 가 같으면 를 반환한다
		return width*height!=0 && width==height;
	}

	double calcArea()
	{
		return width * height;
	}
}

class Circle extends Shape
{
	double r; // 반지름
	Circle(double r)
	{
		this(new Point(0,0),r); // Circle(Point p, double r)를 호출
	}

	Circle(Point p, double r)
	{
		super(p); // . 조상의 멤버는 조상의 생성자가 초기화하도록 한다
		this.r = r;
	}

	double calcArea()
	{
		return Math.PI * r * r;
	}
}

class Point
{
	int x;
	int y;

	Point()
	{
		this(0,0);
	}

	Point(int x, int y)
	{
		this.x=x;
		this.y=y;
	}

	public String toString()
	{
		return "["+x+","+y+"]";
	}
}

 

 

7-23. 문제 7-22에서 정의한 클래스들의 면적을 구하는 메소드를 작성하고 테스트하시오.

1. 메서드명 : sumArea
기능 : 주어진 배열에 담긴 도형들의 넓이를 모두 더해서 반환한다.
반환타입 : double
매개변수 : Shape[] arr

 

class Exercise7_23
{
	/*
		(1) sumAred
	*/

	public static void main(String[] args)
	{
		Shape[] arr = {new Cicle(5.0), new Ractangle(3, 4), new Circle(1)};
		System.out.println("면접의 합 : " + sumArea(arr));
	}
}

- 실행결과
면적의 합 : 93.68140899333463

 

☞

static double sumArea(Shape[] arr)
{
	double sum = 0;
	
	for(int i=0; i<arr.length; i++)
		sum += arr[i].calaArea();

	return sum;
}

 

 

7-24. 다음 중 인터페이스의 장점이 아닌 것은?

a. 표준화를 가능하게 해준다.
b. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
c. 독립적인 프로그래밍이 가능하다.
d. 다중상속을 가능하게 해준다.
e. 패키지간의 연결을 도와준다.

☞ e. 패키지간의 연결을 도와준다.


7-25. Outer 클래스의 내부 클래스 Inner의 멤버변수 iv의 값을 출력하시오.

class Outer
{
	class Inner
	{
		int iv=100;
	}
}

class Exercise7_25
{
	public static void main(Strnig[] args)
	{
		/*
			(1)
		*/
	}
}

- 실행결과
100

 

☞
Outer o = new Outer();
Outer.Inner ii = o.new Inner();
System.out.println(ii, iv);

내부 클래스(인스턴스 클래스)의 인스턴스를 생성하기 위해서는 먼저 외부클래스의 인스턴스를 생성해야 한다. 왜냐하면 '인스턴스 클래스'는 외부 클래스의 '인스턴스 변수'처럼 외부 클래스의 인스턴스가 생성되어야 쓸 수 있기 때문이다.

 

 

7-26. Outer 클래스의 내부 클래스 Inner의 멤버변수 iv의 값을 출력하시오.

class Outer
{
	class Inner
	{
		int iv=200;
	}
}

class Exercise7_26
{
	public static void main(Strnig[] args)
	{
		/*
			(1)
		*/
	}
}

- 실행결과
200

 

☞
Outer.Inner ii = new Outer.Inner();
System.out.println(ii, iv);

스태틱 클래스는 인스턴스 클래스와 달리 외부 클래스의 인스턴스를 생성하지 않고도 사용할 수 있다. 마치 static 멤버를 인스턴스 생성없이 사용할 수 있는 것처럼.

 

 

7-27. 다음과 같은 실행결과를 얻도록 (1) ~ (4) 의 코드를 완성하시오.

class Outer
{
	int value = 10;

	class Inner
	{
		int value = 20;

		void method1()
		{
			int value = 30;
			
			System.out.println(1);
			System.out.println(2);
			System.out.println(3);
		}
	}
}

class Exercise7_27
{
	public static void main(String[] args)
	{
		(4)
	}
}

- 실행결과
30
20
10

☞
(1) System.out.println(value);
(2) System.out.println(this.value);
(3) System.out.println(Outer.this.value);
(4)
Outer outer = new Outer();
outer.Inner inner = new outer.Inner();

inner.method();


외부 클래스와 내부 클래스에 같은 이름의 인스턴스 변수가 선언되었을 때, 외부 클래스의 인스턴스 변수는 내부 클래스에서 '외부클래스이름.this.변수이름' 으로 접근할 수 있다. 내부 클래스의 종류가 인스턴스 클래스이기 때문에 외부 클래스의 인스턴스를 생성한 다음에야 내부 클래스의 인스턴스를 생성할 수 있다.


7-28. 아래의 EvenHandler를 익명 클래스(anonymous class)로 변경하시오.

import java.awt.*;
import java.awt.event.*;

class Exercise7_28
{
	public static void main(String[] args)
	{
		Frame f = new Frame();
		f.addWindowListener(new EventHandler());
	}
}

class EventHandler extends WindowAdapter
{
	public void windowClosing(WindowEvent e)
	{
		e.getWindow().setVisible(false);
		e.getWindow().dispose();
		System.exit(0);
	}
}

 

☞

import java.awt.*;
import java.awt.event.*;

class Test3
{
	public static void main(String[] args)
	{
		Frame f = new Frame();
		f.addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				e.getWindow().setVisible(false);
				e.getWindow().dispose();
				System.exit(0);
			}
		});
	}
}

 

 

7-29. 지역 클래스에서 외부 클래스의 인스턴스 멤버와  static 멤버에 모두 접근할 수 있지만, 지역변수는 final이 붙은 상수만 접근할 수 있는 이유는 무엇인가?

☞ 메소드가 수행을 마쳐서 지역변수가 소멸된 시점에도, 지역 클래스의 인스턴스가 소멸된 지역변수를 참조하려는 경우가 발생할 수 있기 때문에

'Java > Day23' 카테고리의 다른 글

[Java] 자바의 정석 Chapter8. 예외처리(Exception Handling) - 연습문제  (0) 2021.12.05
    'Java/Day23' 카테고리의 다른 글
    • [Java] 자바의 정석 Chapter8. 예외처리(Exception Handling) - 연습문제

    티스토리툴바