package _07_객체지향프로그래밍2;
class SutdaDeck{
final int CARD_NUM = 20;
SutdaCard[] cards = new SutdaCard[CARD_NUM];
SutdaDeck() {
/*
* 배열 SutdaCard초기화
*
*/
}
}
class SutdaCard{
int num;
boolean isKwang;
SutdaCard(){
this(1,true);
}
SutdaCard(int num, boolean isKwang){
this.num = num;
this.isKwang = isKwang;
}
@Override
public String toString() {
return num + (isKwang? "K":"");
}
}
public class EX7_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,
[나의 풀이]
SutdaDeck() {
//1~20까지 1-10순으로 숫자 초기화 **숫자가 1,3,8의 경우 둘 중 하나는 광
int num = 1;
for (int i = 0; i < CARD_NUM; i++) {
if (i == 10) num = 1;
if (i+1 == 1 || i+1 == 3 || i+1 == 8) {
cards[i] = new SutdaCard(num++,true);
}else {
cards[i] = new SutdaCard(num++,false);
}
}//end for
}//SutdaDeck()
[남궁성님 풀이]
for (int i = 0; i < cards.length; i++){
//숫자를 넣어줄 변수
int num = i % 10 + 1; //i가 0일때 > 1, i가 1일때 >2...i가 10일때 > 1
boolean isKwang = (i < 10) && (num == 1 || num == 3 || num == 8);
cards[i] = new SutdaCard(num, isKwang);
}
엄청나게 간결해진 코드. 객체 생성자의 매개변수에 연산식을 줌으로써 코드를 확 줄였다.
▶ 내가 잡고 가야할 점 : 복잡한 조건문을 쓰기 보다, 변수 자체에 연산식을 사용하는 법을 먼저 고려해보자.
package _07_객체지향프로그래밍2;
class SutdaDeck2{
final int CARD_NUM = 20;
SutdaCard2[] cards = new SutdaCard2[CARD_NUM];
SutdaDeck2() {
//문제 7_1 정답
}//SutdaDeck()
//(1) 정의된 세개의 메서드 작성
}
class SutdaCard2{
int num;
boolean isKwang;
SutdaCard2(){
this(1,true);
}
SutdaCard2(int num, boolean isKwang){
this.num = num;
this.isKwang = isKwang;
}
@Override
public String toString() {
return num + (isKwang? "K":"");
}
}
public class EX7_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() {
SutdaCard2 tmp;
int ran = 0;
for (int i = 0; i < cards.length; i++) {
ran = (int)(Math.random()*cards.length)+1;
tmp = cards[i];
cards[i] = cards[ran];
cards[ran] = tmp;
}
}
SutdaCard2 pick(int index) {
//배열 cards에서 지정된 위치의 SutdaCard를 반환한다
return cards[index];
}
SutdaCard2 pick() {
//배열 cards에서 임의의 위치의 SutdaCard를 반환
int ran = (int)(Math.random()*cards.length)+1;
return cards[ran];
}
[남궁성님 풀이]
void shuffle() {
for(int i=0; i<cards.length;i++) {
int j = (int)(Math.random()*cards.length);
// cards[i] cards[j] . 와 의 값을 서로 바꾼다
SutdaCard tmp = cards[i];
cards[i] = cards[j];
cards[j] = tmp;
}
}
SutdaCard pick(int index) {
if(index < 0 || index >= CARD_NUM) // index의 유효성을 검사한다
return null;
return cards[index];
}
SutdaCard pick() {
int index = (int)(Math.random()*cards.length);
return pick(index); // pick(int index)를 호출한다
}
매개변수의 유효성을 고려하지 않았다! 오마이갓 (잊어버림)
▶ index가 0보다 작거나 또는 배열의 범위를 넣어가버린다면 예외(ArrayIndexOutOfBounds)가 발생할 거다.
▶ 항상 메소드를 작성할 때는 수식을 쓰기 전에 매개변수의 유효성을 고려하자! (<<제발 ㅠ)
[나의 답변]
오버라이딩은 부모로부터 상속받은 메소드를 자식이 새롭게 재정의 하는 것을 말한다.
오버라이딩은 다형성과도 연관이 있는데,
일반 클래스, 추상 클래스, 인터페이스로부터 상속받은 메소드를 자식이 오버라이딩할 수 있으면,
(1) 불필요한 코드의 중복을 줄일 수 있고
(2) 개발자가 다수의 메소드를 생성하고 익히지 않고도 단순히 기존 메소드를 재정의함으로 원하는 기능을 다향하게 구현할 수 있다.
[남궁성님 답변]
오버라이딩이란, 조상클래스로부터 상속받은 메서드를 자손 클래스에 맞게 재정의 하는 것을 말한다.
조상 클래스로부터 상속받은 메서드를 자손 클래스에서 그대로 사용할 수 없는 경우가 많기 때문에 오버라이딩이 필요하다.
[나의 답변]
c. 더 넓은 범위여야 한다.
d.
[남궁성님 답변]
c. 접근 제어자는 조상의 메서드 보다 더 넓은 범위여야 한다.
d. 조상의 메서드 보다 더 많은 수의 예외를 선언할 수 있다. -- 긴가민가 했던 부분
[나의 답변]
Tv의 부모인 Product클래스에서 (매개변수가 없는) 디폴트 생성자가 적혀있지 않다.
매개변수를 가진 생성자를 형성하면, 디폴트 생성자는 컴파일러가 자동 생성해주지 않기 때문에
Product(){ } 를 개발자가 입력해주어야 한다.
[나의 답변]
자손 클래스 생성자에서 super() 를 통해 자손 클래스의 변수와 메서드를 상속받기 때문이다.
[남궁성님 답변]
![](https://blog.kakaocdn.net/dn/bto1Jm/btrzkyB3anK/wgoVEo2qRZtZ1c00nNapIK/img.png)
▶ 다시 생각해볼 부분 :
- 초기화는 기본값 -> 명시적 초기화 -> 인스턴스 초기화 블럭 -> 생성자 순으로 간다.
- 만약 상속을 했다면, 여기에서 플러스로
내 생성자 -> 부모 생성자 : 부모의 변수를 초기화 -> 부모 변수 값 물려받음
- 만약 내 생성자에서 변수값을 고치지 않는다면 부모 변수 값이 유지될 것이다.
[나의 답변]
*호출 순서는 들어온 순서란 건가..? 스택에 쌓이는 순서는 child부터일텐데..
호출 순서 : Child(){} -> Parent(){} -> Parent(int x) -> Child(int x)
실행 결과 : 1000
[남궁성님 답변]
Child() -> Child(int x) -> Parent() -> Parent(int x)
실행 결과는 x = 200
- 해설 :
![](https://blog.kakaocdn.net/dn/bmgPdC/btrzldRYa0Q/JotPG05poIeQJw2DdStWZk/img.png)
![](https://blog.kakaocdn.net/dn/uO066/btrzi240DzS/koYN8AYmIH3Xe2a9DsdlN0/img.png)
▶ 다시 생각할 부분 : this()로 나 자신의 다른 생성자를 호출하면 컴파일러는 super()를 자동 생성하지 않는다.
[나의 답변] b --- 틀렸다! 패키지 밖에서 상속을 받으면 접근범위가 당연히 디폴트보다 넓을 텐데 왜 생각을 못했지ㅋㅋ 기왕 틀린 김에 한 번 더 숙지하고 가야겠다
[남궁성님 해설] 답은 a다.
![](https://blog.kakaocdn.net/dn/1F1Pq/btrziSOCxCW/oKXVTiIm8J3RXpOkZuliz1/img.png)
[나의 답변]
(궁금증.. a 보니까 든 생각. 상수는 전역(맴버필드)에 붙이는게 낫지 않을까. 지역변수에 쓰는 경우도 있을까?)
c. 오버로딩은 되는데, 오버라이딩 불가
[남궁성님의 해설]
![](https://blog.kakaocdn.net/dn/bivuto/btrzkznpSfR/Ft8nwuVhihxKUkbskqgG10/img.png)
[나의 답변]
class MyTv2 {
private boolean isPowerOn;
private int channel;
private int volume;
final int MAX_VOLUME = 100;
final int MIN_VOLUME = 0;
final int MAX_CHANNEL = 100;
final int MIN_CHANNEL = 1;
public void setIsPowerOn(boolean isPowerOn){
this.isPowerOn = isPowerOn;
}
public boolean getIsPowerOn() {
return this.isPowerOn;
}
public void setChannel(int channel) {
this.channel = channel;
}
public int getChannel() {
return this.channel;
}
public void setVolume(int volume) {
this.volume = volume;
}
public int getVolume() {
return this.volume;
}
}//end class
[남궁성님 풀이]
![](https://blog.kakaocdn.net/dn/dENVj4/btrzi3pes5g/ChXtntIFi0jkUbOEaIBgjK/img.png)
-- 정말 private과 getter setter만 만드는데 치중하느라 MIN과 MAX를 설정할 생각을 안했다. 함정이네 함정이야.ㅠ 그런데 현장에서도 늘 이렇게 범위를 고려해야하는 건 맞기에.. 앞으로 생각의 생각을 더 해야겠다.
'Language > Java' 카테고리의 다른 글
[이클립스] 프로젝트의 JDK 버전 변경하기 (0) | 2022.04.26 |
---|---|
[자바_문법] 쓰레드 (0) | 2022.04.17 |
[자바_API] java.lang패키지와 유용한 클래스(1) (0) | 2022.04.08 |
[자바_API] 입출력 I/O (0) | 2022.04.05 |
[자바_API] 네트워킹 (0) | 2022.04.04 |