1. 다음 왼쪽에 있는 클래스가 오른쪽과 같이 선언되어 있습니다.

 

 [이름] CD클래스

==================

[데이터]

관리번호

타이틀

package d1029;

class CDInfo {
	String registerNo;
	String title;
	CDInfo(String registerNo, String title){
		this.registerNo=registerNo;
		this.title=title;
	}

}

 

 

위의 클래스를 이용해서 다음의 클래스를 선언하십시오.

 

[이름] 음악 CD 클래스

==================

[데이터]

관리번호

타이틀

아티스트

곡명[]

class SongsCD extends CDInfo{
	String artist;
	String songs[];
	SongsCD(String registerNo, String title, String artist, String[] songs){
		super(registerNo, title);
		this.artist =artist;
		this.songs=songs;
	}
}

 

 

곡명[]이 배열형태라 선언하는 것이 익숙하지 않아서 어려웠는데, 위 소스와 같이 선언하면 되겠습니다.

this.배열명 = 배열명;

왜 this.songs[]=songs[]가 아닌 this.songs=songs 인가?

배열은 레퍼런스 타입입니다. 이미 선언되어있는 배열의 주소값을 가져오는 것이기 때문에 배열명만 적어주면 됩니다.

 

※ 보통 실무에서는 생성자 매개변수에 String[] songs 형태로 넣기보다는 int형식으로 받아서,

songs = new String[받아온 int값]; 으로 배열을 생성하는 경우가 많습니다.

 

위의 클래스를 확인하는 메인 클래스

class test2 {
	public static void main(String[] args) {
		String songs[]={"A곡","B곡","C곡"}; 
		//먼저 곡명을 배열로 선언합니다.
		SongsCD s = new SongsCD("abc","제목!!","아티스트",songs); 
		//생성자에서 배열명을 써서 초기화합니다.
		System.out.println(""+s.registerNo+" "+s.title+" "+s.artist+" "+s.songs[0]+s.songs[1]);
	}
}

 

 

2. 직사각형을 표현하는 다음과 같은 클래스가 있습니다.

class Rectangle {
	private int width, height;
	Rectangle(int width, int height){
		this.width = width;
		this.height = height;
	}
	int getWidth(){
		return width;
	}
	int getHeight(){
		return height;
	}
	
}

 

다음은 위의 클래스를 상속해서 만든 정사각형을 표현하는 클래스입니다. 밑줄 친 부분을 적절하게 채우십시오.

class Square a)extends Rectangle{
	Square(int sideLength){
		b)super(sideLength, sideLength);
	}
	int getSideLength(){
		return c)super.getWidth();
	}
}

Square클래스는 Rectangle 클래스를 상속받기 때문에 a)는 extends Rectangle입니다.

 

Rectangle클래스에 생성자가 존재하기 때문에, 상속받는 Square클래스에서는 생성자를 반드시 선언해야 하며, 상위 클래스의 생성자를 사용해야합니다. 그 형태는 super형태로 사용하게 되는데, 정사각형을 만드는 클래스 생성자이기 때문에, 매개변수는 sideLength 하나로 상위클래스 매개변수 자리에 동일하게 넣어줍니다(super(sideLength, sideLength)). 흔히 착각하는 것중에 상위클래스의 생성자를 하위클래스에서 super형태로 쓸 때, 매개변수까지 동일해야한다는 착각을 하게됩니다. 하지만 매개변수까지 같을 필요는 없고 매개변수 개수와 형태만 같으면 됩니다.

 

마지막으로 getSideLength()메소드는 상위메소드인 getWidth()나 getHeight()둘중 하나를 super로 써서 사용하면 됩니다. 여기에서는 상위클래스의 필드가 private로 선언되었다는 것에 주의해야합니다. private로 선언된 필드는 같은 클래스 내에서만 사용이 가능합니다. 상위클래스를 살펴보니 메소드는 가져다 쓸수 있게 되어있습니다. 그러므로 c)는 super.getWidth(); super.getHeight();입니다.

 

 

3. 다음의 프로그램은 이 장에서 작성한 Lendable 인터페이스와 AppCDInfo, SeparateVolume클래스를 사용하는 프로그램인데 잘못된 부분이 있습니다. 그 부분을 찾아서 수정하십시오.

 

Interface Lendable.

interface Lendable {
    final static byte STATE_BORROWED = 1;   // 대출 중
    final static byte STATE_NORMAL = 0;     // 대출되지 않은 상태
    void checkOut(String borrower, String date); 
    void checkIn(); 
}

 

 

class AppCDInfo.

package d1029;
class AppCDInfo  extends CDInfo  implements Lendable  {
    String borrower;         // 대출인
    String checkOutDate;     // 대출일
    byte state;              // 대출상태
    AppCDInfo(String registerNo, String title) {
        super(registerNo, title);
    }
    public void checkOut(String borrower, String date) {   // 대출한다
        if (state != 0)
            return;
        this.borrower = borrower;
        this.checkOutDate = date;
        this.state = 1;
        System.out.println("*" + title + " CD가 대출되었습니다.");
        System.out.println("대출인:" + borrower);
        System.out.println("대출일:" + date + "\n");    
    }
    public void checkIn() {   // 반납한다
        this.borrower = null;
        this.checkOutDate = null;
        this.state = 0;
        System.out.println("*" + title + " CD가 반납되었습니다.\n");
    }
}

 

 

class SeparateVolume.

class SeparateVolume  implements Lendable  {
    String requestNo;      // 청구번호
    String bookTitle;      // 제목
    String writer;         // 저자
    String borrower;       // 대출인
    String checkOutDate;   // 대출일
    byte state;            // 대출상태
    SeparateVolume(String requestNo, String bookTitle, 
                   String writer) {
        this.requestNo = requestNo;
        this.bookTitle = bookTitle;
        this.writer = writer;
    }
    public void checkOut(String borrower, String date) {   // 대출한다
        if (state != 0)
            return;
        this.borrower = borrower;
        this.checkOutDate = date;
        this.state = 1;
        System.out.println("*" + bookTitle + " 이(가) 대출되었습니다.");
        System.out.println("대출인:" + borrower);
        System.out.println("대출일:" + date + "\n");    
    }
    public void checkIn() {   // 반납한다
        this.borrower = null;
        this.checkOutDate = null;
        this.state = 0;
        System.out.println("*" + bookTitle + " 이(가) 반납되었습니다.\n");
    }
}

 

 

 

 

class TestExample

class TestExample { public static void main(String[] args) { Lendable arr[]={ new AppCDInfo("2005-7001", "Redhat Fedora"), new SeparateVolume("859ㅂ986ㅊ","책상은 책상이다","빅셀")}; checkOutAll(arr,"김수진","20060318"); } static void checkOutAll(Lendable arr[], String borrower, String date){ for(Lendable obj:arr){ obj.checkOut(borrower, date); System.out.println("대출인 : "+obj.borrower);//이 부분에서 obj.borrower를 borrower로 변경하거나 삭제 System.out.println("대출일 : "+obj.checkOutDate);//이 부분에서 obj.checkOutDate를 date로 변경하거나 삭제 } } }

 

 

TestExample 클래스에서 잘못된 부분은 obj.borrower와 obj.checkOutDate가 있는 11, 12라인입니다.

여기서 obj는 Lendable로 선언되어있습니다. Lendable이라는 인터페이스에는 borrower나 checkOutDate라는 필드가 없고, 있다하더라도 인터페이스이기 때문에 상수필드 형태로 선언되어져 있어야합니다. 그러므로 이 소스코드를 정상적으로 작동시키려면 11, 12라인을 삭제하거나, borrower와 date로 변경하면 되겠습니다.

 

 

4. 다음과 같은 인터페이스 선언은 문법적으로 잘못이기 때문에 컴파일 에러가 발생합니다. 어느부분이 잘못되었는지 찾으십시오.

 

interface MessageSender {
	String title;
	String senderName;
	MessageSender(String title, String senderName){
		this.title=title;
		this.senderName=senderName;
	}
	abstract void sendMessage(String recipient);
}

 

인터페이스는 상수필드와 추상메소드만 선언이 가능합니다. String title; String senderName에 만약 초기값이 주어져서 String title="제목예제"; String senderName="보내는이"; 이런식으로 선언되었더라면 final static이 안붙어있더라도 인터페이스이기 때문에 자동으로 내부에 final static을 붙여주게 되서 에러가 생기지 않겠지만, 여기에서는 초기값이 주어지지 않았기 때문에 2,3라인을 삭제해주어야 합니다. 그리고 이어서 MessageSender라는 생성자가 등장합니다. 인터페이스에는 생성자를 선언할 수 없으므로 이 부분도 삭제해줍니다.