20210926 일요일

DUUUPPAAN·2021년 9월 26일
0

교육 20210915~ Java

목록 보기
7/13

·건너뛴 토요일

-토요일, 벨로그를 작성해야 한다는 사실을 잊었다. 코드를 보긴 했지만, 오늘도 작성해야 하는구나란 생각을 못했다. 긴 연휴동안 '쉬는 시간==베로그 작성을 안하는 시간'이 되어버린 느낌이었다. 아직 습관도 안잡혔는데, 무턱대고 쉬니까 이렇게 되는 것 같다. 인정하자! 스스로와의 약속을 어겼다. 그렇지만 이제부터 열심히 잘 챙겨서 쓰도록 하자!

·8시 기상 후, 1시까지

-아침에 일어나서, 벨로그를 작성하지 않았다는 것을 깨달았다. 그래서 최대한 공부를 하고 꼭 벨로그를 작성해야겠다고 생각했다. 교재를 펼치고 코드를 따라하고, 이해가 안되는 부분을 찾아봤다. 내가 금요일날 진행했던 코드들이, 사실 찬찬히 뜯어보니 이해를 못한 부분이 굉장히 많았다는 것을 깨달았다.

객체를 생성할 때 초기화를 시켜주는 부분, '아~ 그렇구나.'정도로만 넘어갔다. '그냥 클래스와 같은 이름의 초기화 부분만 작성해주면 되는거겠구나. 객체를 생성할 때만 사용하면 되는거구나'하고 넘어가려 했다. 그런데, 이게 교재의 코드를 따라만 쓰면 되는 것이라면 맞겠지만, 나는 이제 직접 코드를 작성하고, 실행하고 오류를 찾아내고 해야 한다. 그런데 과연 이렇게 어물쩡 넘어가는 것이 맞는것인지 의문이 갔다.

교재의 설명은 구체적이고 충분하지는 않았다. 그래서 해당 내용에 대한 것을 구글에서 검색해봤고, 여러 블로그를 찾아봤다. 그래서 정리한 결과

생성자: 클래스 명과 같은 이름의 메소드.
굉장히 중요한 부분이다. 바로 메소드! 메소드다!
단, 이 메소드는 반환형을 선언하지 않는다. 여기서 반환형을 선언하지 않는다는 것은, void처럼 반환형을 받지 않겠다와는 다른 의미이다. 그냥 반환여부자체가 없다는 뜻이다.
즉, 초기화 작업만 하고, 메소드의 이름은 클래스 이름이며, 반환은 하지 않고, 입력은 있지만 출력은 없다.

객체를 생성할 때 작성하는 코드를 살펴보자.

예를 들어,

Aircon ac = new Aircon();

위처럼 객체를 만든다고 했을 때, Aircon()이 부분이 초기화를 시켜주는 생성자이다. (내 이해가 맞는지는 모르겠지만,) new 연산자를 통하고, 클래스 명과 똑같은 이름의 메소드를 사용해서 객체를 만들어주는 것이다. 전에는 저 뒤에 괄호를 왜 붙이는 것인지 이해가 가지 않았다. 그냥 으례 그렇게 해온 것인가 싶었는데, 저렇게 메소드라고 생각하니 이해가 쉽게 되었다.

자 그러면, 금요일날 벨로그에 썼던, 객체생성을 위한 메소드를 지금까진 따로 정의해주지 않았는데, 인자가 있다면 빈 메소드도 만들어줘야 한다는 부분도 완벽하게 이해가 된다.

Aircon ac1 = new Aircon();
Aircon ac2 = new Aircon(30);

위의 두 객체를 생성한다고 하자. 그럼, 초기화 시켜주는 메소드가 몇 개가 필요할까? 만약

public Aircon(int temp){
	this.temp = temp;
}

위의 메소드만 있다고 생각해보자.
ac2라는 객체를 생성하는 데에는 성공할 것이다. 왜냐하면, 보내는 인자에 해당하는 파라미터를 가진 메소드가 있기 때문이다. 그러나, ac1의 경우에는? 빈 인자를 받아주는 빈 파라미터를 가진 메소드가 없다. 그러면 컴파일 오류가 날 것이다. 이렇게 이해하니 엄청나게 이해가 수월했다.

수업 시간에는 넘어갔지만 교재에는 있던 this()에 대해서도 봤다. 새로운 것이라기 보다는 코드의 중복을 피해기 위해서 간단하게 작성하는 기능이었다. 지금은 this.과 좀 헷갈릴 수 있어서 설명을 피하신 것 같았다.

·교재에 있는 문제 안보고 작성해보기

-입력값을 받아 해당 값까지의 팩토리얼 값과 해당 값까지의 제곱합을 구하는 문제다.
예를 들어 5를 입력하면, 5팩토리얼을 구하고, 11+22+33+44+5*5.
물론 클래스는 2개를 만들어서 한쪽에서는 기능을, 한쪽에서는 기능을 불러와서 사용하기만 한다.

package Calculate;

public class Calculate {

	int getFactorial(int num) {
		int result = 1;
		for(int i=num;i>0;i--) {
			result = result*i;
		}
		return result;
	}
	
	int getPower(int num) {
		int result = 0;
		for(int i=num;i>0;i--) {
			result= result+i*i;
		}
		return result;
	}
	
	
}

위에서 팩토리얼을 구하는 메소드와 제곱합을 구하는 메소드를 작성했다.

package Calculate;

import java.util.Scanner;

public class CalculateMain {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Calculate cal = new Calculate();
		
		System.out.print("팩토리얼을 구할 값을 입력해주세요: ");
		int addNum = sc.nextInt();
		
		System.out.println("답: "+cal.getFactorial(addNum));
		
		System.out.println("------------------------");
		
		System.out.print("1부터 시작해 입력한 값까지의 제곱의 합을 구합니다. 값을 입력하세요: ");
		int inputNum = sc.nextInt();
		System.out.println("답: "+cal.getPower(inputNum));
	}

}

그리고 main이 되는 클래스에서 해당 메소드들을 사용했다. 이정도의 구현은 헷갈릴 일도 없었다.

·헷갈렸던 search 코드

교재에서 진행했던 코드가 있다.
0. 사용할 변수를 선언하고 초기화하는 클래스를 만든다.(단, private를 사용한다. getXXX와 SetXXX를 만들어준다.)
1. 5명의 회원정보가 있다. 회원정보는 배열 객체를 만들어서, 집어넣는다.
2. 입력값을 받고, 그 입력값이 회원정보에 있는 이름과 일치하는지를 확인하는 클래스를 만든다.
3. 파라미터로 받은 번호에 해당하는 회원정보 전체를 출력해주는 클래스를 만든다.
4. SearchMain 클래스를 만들어서 입력값을 받는다.(이름) 해당 입력값을 2번의 메소드를 이용해 일치를 확인하고, 해당 결과를 3번의 메소드를 사용해 출력한다. 단, 만약 일치하는 회원정보가 없으면, 다시 입력하도록 한다.

사실 교재에는 2와 3을 같은 클래스에 만들었다. 회원정보를 넣는 코드도 같은 클래스에 만들어서 클래스 하나가 굉장히 길다. 그래서 더더욱 이해가 쉽지 않았다. 위처럼 0~4번 인덱스를 만들어 설명해주지도 않았다. 그래서 나는 직접 구현해야하는 기능들을 생각했고, 해당 기능들을 어떤 순서로 만들어야 하는지 공책에 작성했다. 물론 작성하는 과정에서 1번이 4번과 함께 있는 것이 가장 적절하다고 생각되어 수정을 했었다. 그렇지만 기본적인 맥락은 같다. 결국, 교재에서와는 많이 다른 코드를 작성했다. 구현하는 기능도, 사용한 것들도 비슷하지만, 교재보다 클래스가 하나 더 많고, 좀 더 직관적이다. 그래서 더 만족했다. 이해를 했으니 해당 코드를 작성했다는 점이기 때문이다.

단, 작성 과정에서 문제가 있었다.

Member[] mt = new Member[5];
	
	public AnswerSearch() {
		mt[0] = new Member("가씨",180 ,75 , "대한민국");
		mt[1] = new Member("나씨",165 ,42 , "미국");
		mt[2] = new Member("다씨",175 ,99 , "일본");
		mt[3] = new Member("라씨",170 ,55 , "중국");
		mt[4] = new Member("마씨",159 ,45 , "인도");
	}

교재에 이런 부분이 있었다. 그런데, 대체 왜 배열 객체를 생성하고 밑에 또 new 연산자를 또 사용해야 하는 것인지 이해가 가지 않았다. 심지어 밑에 있는 mt앞에는 Member도 붙어있지 않다. 대체 왜?
심지어 지금 위의 배열은 2차원 배열이 아닌 것인가? 구조는 2차원 배열같은데 어째서 []이건 한쌍밖에 없는것이지?
의문점 투성이었다.
나는 mt[0].name = "가씨"; 이런식으로 값을 넣어줘야할 것 같은데, new 연산자를 사용하는 것도 도무지 모르겠는 것이다.

그래서 찾아봤다. 구글링 만세
굉장히 쉬운 문제인데 간과했었다.
Member[] mt = new Member[5];
이 부분을 자세하게 이해하자면, mt는 배열이다. 그런데, 그 배열은 객체를 담는 배열이다. 즉, new라는 연산자로 배열(객체)을 만들고, 그 객체들을 다시 mt라는 배열객체에 넣어주는 것이다. 그래서 new 연산자를 6번이나 써준 것이다. 이 부분이 이해되니까 상당히 많은 부분에 대한 의문이 풀렸다.

package Search;

public class Member {
	private String name;
	private int height;
	private int weight;
	private String nation;
	
	public Member(String name, int height, int weight, String nation) {
		this.name = name;
		this.height = height;
		this.weight = weight;
		this.nation = nation;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name=name;
	}

	public int getHeight() {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}

	public int getWeight() {
		return weight;
	}

	public void setWeight(int weight) {
		this.weight = weight;
	}

	public String getNation() {
		return nation;
	}

	public void setNation(String nation) {
		this.nation = nation;
	}
	
	
}

0번에 해당하는 코드

package Search;

public class AnswerSearch {
	
Member[] mt = new Member[5];
	
	public AnswerSearch() {
		mt[0] = new Member("가씨",180 ,75 , "대한민국");
		mt[1] = new Member("나씨",165 ,42 , "미국");
		mt[2] = new Member("다씨",175 ,99 , "일본");
		mt[3] = new Member("라씨",170 ,55 , "중국");
		mt[4] = new Member("마씨",159 ,45 , "인도");
	}
	
	void answerS(int i) {
		System.out.println("----------------");
		System.out.println("이름: "+ mt[i].getName());
		System.out.println("키: "+ mt[i].getHeight());
		System.out.println("몸무게: "+ mt[i].getWeight());
		System.out.println("국적: "+ mt[i].getNation());
	}
}

원래는 1번과 3번으로 나뉘어 있는 순서도였는데, 1번과 3번을 나누면 더 복잡해지기 때문에, 작성하는 과정에서 한 클래스로 합쳤다.

package Search;

public class SearchService {
	
	AnswerSearch as = new AnswerSearch();
	
	boolean SearchS(String name) {
		boolean result = false;
		for(int i=0;i<as.mt.length;i++) {
			if(as.mt[i].getName().equals(name)) {
				//출력 메소드 넣기.
				/*answerS(mt[i]);*/
				as.answerS(i);
				result = true;
			}
		}
		return result;
	}
}

2번에 해당하는 클래스이다. 중간에 주석을 넣은 이유는 나중에 메소드 이름을 확실하게 보고 오기 위해서 입력해놨다.
여기서 주의할 부분은 boolean result = false; 이 부분일 것이다. 로컬변수는 항상 명시적으로 초기화해줘야 한다는 점!

package Search;

import java.util.Scanner;

public class SearchMain {

	public static void main(String[] args) {
	
	Scanner sc = new Scanner(System.in);
	
	
	SearchService searchSs = new SearchService();
	
	do {
		System.out.println("이름 입력: ");
		String name = sc.next();
		boolean searchResult = searchSs.SearchS(name);
		if(searchResult) break;
		System.out.println("일치하는 이름이 없습니다.");
	}
	while(true);
	
		
	}

}

마지막으로 4번 기능을 하는 메인 코드를 작성했다. 여기에선 do while문을 사용했는데, 처음엔 if문을 사용했다. 그런데 아무리 실행해도 오류는 따로 없는데 입력해달라는 출력부분이 콘솔에 나타나지 않았다. 그래서 결국 do while문으로 바꾸었다. 왜 그런지는 아직도 이해가 정확하게 가지 않았다.

·마지막으로는 상속!

-마지막 코드 연습은 상속이었다. 상속을 해서 상속받은 것들을 활용하는 코드를 (수업시간에 진행했던) 작성했다.

상속에 대한 부분은 이해가 어렵지 않아서 충분히 작성할 수 있었다. 게다가 유일하게 이해가 어렵던 배열 객체에 또 객체를 넣는 부분을 이해할 수 있었기 때문에 수월했다.(위에서 했던 new 6개에 대한 이해.)

·결과적으로 흡족했던 오늘 하루

-금요일날 굉장히 열심히 정리하고 공부했지만, 교재와 수업 시간에는 부족했던 설명들이 있었다. 그래서 나조차도 100%이해를 못하고 있었다는 것을 몰랐다. 그러나 오늘 공부를 통해 정말 잘 깨닫게 되었고, 이해 못한 부분을 이해할 수 있게 되는 시간이었다. 앞으로도 주말에 찬찬히 코드들을 뜯어보면서 100%이해를 할 수 있는 시간을 가져야겠다.

profile
비전공자란 이름으로 새로운 길을 가려 하는 신입

0개의 댓글