남궁성님의 자바의 정석
1. Chaper 7 - 객체지향
다음 중 오버라이딩의 조건으로 옳지 않은 것은? (모두 고르시오)
a. 조상의 메서드와 이름이 같아야 한다.
b. 매개변수의 수와 타입이 모두 같아야 한다.
c. 접근 제어자는 조상의 메서드보다 좁은 범위로만 변경할 수 있다.
d. 조상의 메서드보다 더 많은 수의 예외를 선언할 수 있다.
[정답] c, d
자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와
- 이름이 같아야 한다.
- 매개변수가 같아야 한다.
- 리턴타입이 같아야 한다.
자손 클래스의 생성자에서 조상 클래스의 생성자를 호출해야하는 이유는 무엇인
가?
[정답] 조상에 정의된 인스턴스 변수들이 초기화되도록 하기 위해서.
자손클래스의 인스턴스를 생성하면 조상으로부터 상속받은 인스턴스변수들도 생성
되는데, 이 상속받은 인스턴스변수들 역시 적절히 초기되어야 한다. 상속받은 조상의 인
스턴스변수들을 자손의 생성자에서 직접 초기화하기보다는 조상의 생성자를 호출함으로써
초기화되도록 하는 것이 바람직하다.
isPowerOn, channel, volume을 클래스 외부에서 접근할수 없도록 제어자를 붙이고 대신 이 멤버변수들의 값을 어디서나 읽고 변경할 수 있도록 getter와 setter메서드를 추가하라
class MyTv2 {
private boolean isPowerOn;
private int channel;
private int volume;
...
public void setVolume(int volume){
if(volume > MAX_VOLUME || volume < MIN_VOLUME)
return;
this.volume = volume;
}
public int getVolume(){
return volume;
}
public void setChannel(int channel){
if(channel > MAX_CHANNEL || channel < MIN_CHANNEL)
return;
this.channel = channel;
}
public int getChannel(){
return channel;
}
....
작성한 MyTv2클래스에 이전 채널(previous channel)로 이동하는 기능의 메서드를 추가해서 실행결과와 같은 결과를 얻도록 하시오.
class MyTv2{
....
private int prevChannel;
....
public void setChannel(int channel){
if(channel > MAX_CHANNEL || channel < MIN_CHANNEL)
return;
prevChannel = this.channel; // 현재 채널을 이전 채널에 저장한다.
this.channel = channel;
}
...
public void gotoPrevChannel() {
setChannel(prevChannel); // 현재 체널을 이전 채널로 변경한다.
}
public class Ex_5 {
public static void main(String[] args){
MyTv2 t = new MyTv2();
t.setChannel(20);
System.out.println("CH:"+t.getChannel());
t.gotoPrevChannel();
System.out.println("CH:"+t.getChannel());
CH:20
CH:10
세 개의 클래스로부터 공통부분을 뽑아서 Unit이라는 클래스를 만들고, 이 클래스를 상속받도록 코드를 변경하시오
abstract class Unit {
int x, y;
abstract void move(int x, int y); // 추상클래스
void stop() { /* 현재 위치에 정지 */ }
}
class 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() { /* 선택된 대상을 내린다.*/ }
}
다음은 물건을 구입하는 사람을 정의한 Buyer클래스이다. 이 클래스는 멤버변수로 돈(money)과 장바구니(cart)를 가지고 있다. 제품을 구입하는 기능의 buy메서드와 장바구니에 구입한 물건을 추가하는 add메서드,
구입한 물건의 목록과 사용금액, 그리고 남은 금액을 출력하는 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 가진 돈과 물건의 가격을 비교해서 가진 돈이 적으면 메서드를 종료한다.
if(money < p.price) {
System.out.println("잔액이 부족하여 "+ p +"을/를 살수 없습니다.");
return;
}
// 1.2 가진 돈이 충분하면, 제품의 가격을 가진 돈에서 빼고
money -= p.price;
// 1.3 장바구니에 구입한 물건을 담는다.(add메서드 호출)
add(p);
}
void add(Product p) {
// 1.1 i의 값이 장바구니의 크기보다 같거나 크면
if(i >= cart.length) {
// 1.1.1 기존의 장바구니보다 2배 큰 새로운 배열을 생성한다.
Product[] tmp = new Product[cart.length*2];
// 1.1.2 기존의 장바구니의 내용을 새로운 배열에 복사한다.
System.arraycopy(cart,0,tmp,0,cart.length);
// 1.1.3 새로운 장바구니와 기존의 장바구니를 바꾼다.
cart = tmp;
}
// 1.2 물건을 장바구니(cart)에 저장한다. 그리고 i의 값을 1 증가시킨다.
cart[i++]=p;
} // add(Product p)
void summary() {
String itemList = "";
int sum = 0;
for(int i=0; i < cart.length;i++) {
if(cart[i]==null)
break;
// 1.1 장바구니에 담긴 물건들의 목록을 만들어 출력한다.
itemList += cart[i] + ",";
// 1.2 장바구니에 담긴 물건들의 가격을 모두 더해서 출력한다.
sum += cart[i].price;
}