연습 문제 (3) 답지
각 문제의 풀이. 전)/후)는 코드 수정 형식.
1
1-a)
- a) 문제 없음
- c) 출력
212100 * 9 / 5 + 32→ 900 / 5 = 180 → 180 + 32 = 212- 정수 나눗셈이지만 900은 5로 나누어떨어짐
“### 1-b)
- a) 컴파일 오류
this(...)생성자 호출은 생성자 본문의 첫 문장이어야 함.this.name = name;뒤에 와서 오류
- b)
전) public User(String name) { this.name = name; this(name, 0); } 후) public User(String name) { this(name, 0); } - c) (고친 경우 출력)
Kim 0User("Kim")→this("Kim", 0)→ name=Kim, age=0
1-c)
- a) 문제 없음
- c) 출력
66 B 3 3.5'A'는 65 →c + 1= 66 (char가 int로 승격)(char) 66→ ‘B’7 / 2는 정수 나눗셈 → 3(double) 7 / 2→ 7.0 / 2 = 3.5 (캐스팅이 나눗셈보다 먼저)
2
- 출력
10 20 99swap은 지역 매개변수x,y만 교환 → 호출부 b1, b2엔 영향 없음 (10, 20 그대로)change는 받은 참조로 원본 개체를 변경 →b1.setValue(99)→ 99- 참조형 인자: 참조(주소)는 값으로 복사되므로 재할당은 호출부 무관, 멤버 변경은 반영됨
3
- 캡슐화(encapsulation): 함수의 black box(추상화) 개념을 클래스 단위로 확장한 것. 데이터(멤버 변수)와 그 데이터를 다루는 메서드를 하나로 묶고, 멤버 변수를
private으로 숨겨 외부의 직접 접근을 막음. 함수를 분리할 때의 원칙을 그대로 적용해, 클래스 안에 중복된 동작이 있으면 private 메서드로 분리 - 추상화(abstraction): OOP에서 추상화란 “어떤 구체적인 것에 직접 손대지 않겠다”는 의미. 이를 바라보는 관점이 두 가지 있음
- 추상 자료형(abstract data type, ADT) 관점
- 사용자는 클래스를 하나의 자료형처럼 사용할 수 있음
- 그 클래스 안에 들어 있는 멤버 변수가 정확히 뭔지 몰라도 됨
- 그냥 클래스로부터 개체를 생성해서 사용
- 절차적 데이터 추상화(procedural data abstraction) 관점
- 데이터를 직접 조작하는 대신 메서드를 호출해서 다룸
- OOP라는 용어를 처음 주창했던 소수설의 관점과 유사 (동적인 개체, behavioral objects 진영)
- 추상 자료형(abstract data type, ADT) 관점
4
- 정적(static) 멤버 변수: 클래스당 하나만 존재하며 모든 인스턴스가 공유함. 인스턴스를 만들지 않아도 클래스 이름으로 접근 가능
- 인스턴스 멤버 변수: 개체(인스턴스)마다 따로 존재하며 각자 값을 가짐
- 정적 메서드에서
this를 쓸 수 없는 이유: 정적 메서드는 특정 인스턴스에 묶이지 않고 클래스에 속함. 호출 시 가리킬 “현재 개체”가 없으므로 그 개체를 의미하는this를 사용할 수 없음 (따라서 인스턴스 멤버에도 직접 접근 불가)
5
5-a)
- a) 컴파일 오류
- 정적 타입이
Vehicle인데Vehicle에는honk()가 없음
- 정적 타입이
- b)
전) Vehicle v = new Car("Sedan"); 후) Car v = new Car("Sedan");- 또는
((Car) v).honk();
- 또는
- c) (고친 경우 출력)
Sedan moves Sedan honks
5-b)
- a) 문제 없음
- c) 출력
car- 실제 개체는
Car→v instanceof Boat는 false,v instanceof Car는 true
- 실제 개체는
5-c)
- a) 런타임 오류 (ClassCastException)
- 컴파일은 통과(
Vehicle→Car다운캐스트 허용)하나, 실제 개체가Boat라Car로 캐스팅 시 예외
- 컴파일은 통과(
- b) 실제 타입(Boat)에 맞게 캐스팅
전) Car c = (Car) v; c.honk(); 후) Boat c = (Boat) v; c.sail();- (고친 경우 출력)
Yacht sails
- (고친 경우 출력)
5-d)
- a) 문제 없음
- c) 출력
Mini honks- 실제 개체가
Car라Car로의 다운캐스트가 성공
- 실제 개체가
6
- 출력
1000 1020 1030nextId는 static → 모든 인스턴스가 공유- a 생성: id=1000, nextId→1010
- b 생성: id=1010, nextId→1020
- c 생성: id=1020, nextId→1030
- a.id=1000, c.id=1020, getNextId()=1030
7
- 출력
Grandparent Parent Child- 상속 계층:
Grandparent ← Parent ← Child new Child()→ 암시적super()가 위로 전파 → 최상위 부모 생성자부터 실행- 즉 생성자 본문은 부모 → 자식 순서(위에서 아래로)로 실행됨
Parent p = new Child()는 유효한 업캐스트 (문제 없음)
- 상속 계층:
8
예시 답안
// Engine.java
package academy.pocu.comp2500;
public class Engine {
private int horsepower;
public Engine(int horsepower) {
this.horsepower = horsepower;
}
public int getHorsepower() {
return this.horsepower;
}
}
// Car.java
package academy.pocu.comp2500;
public class Car {
private String name;
private Engine engine;
public Car(String name, int horsepower) {
this.name = name;
this.engine = new Engine(horsepower);
}
public String getName() {
return this.name;
}
public int getHorsepower() {
return this.engine.getHorsepower();
}
}
// Program.java
package academy.pocu.comp2500;
public class Program {
public static void main(String[] args) {
Car car = new Car("Sedan", 150);
System.out.println(car.getName());
System.out.println(car.getHorsepower());
}
}- 포인트
Car가Engine을 상속(is-a)하지 않고 멤버로 가짐(has-a) → 컴포지션getHorsepower()는 보관한Engine에 위임(delegation)- 멤버 변수는
private으로 두어 캡슐화 유지 - 출력 예:
Sedan/150
9
- 출력
70- 내포(inner) 클래스
Shelf는 바깥 클래스Library의 private 멤버bookCount에 접근 가능 library.new Shelf(20)로 바깥 인스턴스에 묶인 내부 개체 생성store()두 번 →bookCount += 20두 번 → 30 + 20 + 20 = 70
- 내포(inner) 클래스
10
- 이상적인 개체 상태 수정법
- 그 개체의 사용자가 어떤 동작을 지시함
- 그 동작의 결과로 개체 안에 있는 어떤 상태가 바뀜
- 즉, 외부가 멤버 변수를 직접 대입하는 게 아니라 개체 스스로 자신의 상태를 변경(책임)함
- 예:
Classroom에서setScore(index, score)를 호출하면 점수를 저장하면서 평균(mean)도 함께updateMean()으로 갱신 → 사용자가mean을 직접 건드리지 않아도 개체가 일관된 상태를 유지
- 무조건 setter를 추가하면 안 좋은 이유
- setter는 데이터를 직접 바꾸므로 가능하면 피하는 게 좋음
- 중요한 점: 개체가 불확실(불완전)한 상태가 되는 경우를 만드는 게 최대의 악수
- 따라서 setter는 “고민 후” 꼭 필요할 때만 추가
11
- 출력
A honks B sails C honks- 배열의 정적 타입은
Vehicle이지만 실제 개체는 각각 Car/Boat/Car instanceof(RTTI)로 실제 타입을 확인한 뒤 알맞게 다운캐스팅하여 메서드 호출- vehicles[0] Car → honk, [1] Boat → sail, [2] Car → honk
- 배열의 정적 타입은