이번 주 프로그래밍 과제가 2개가 나갔었다. 하나는 계산기 프로그램을 짜는 것으로 필수적으로 해야 하는 것이고, 다른 하나는 호텔 예약 프로그램을 짜는 것으로 선택적으로 해도 되는 것이었다. 시간에 여유가 생겨서라고 했지만 사실 자야 할 3시간을 안 자고 여기에 매달렸다 선택 과제를 해냈는데, 자고 일어나서 이 두 과제에 대해 코드 개선을 진행하며 - Java로 짤 때 썼을 것 같은 코드들을 쓰고 나서 몇개 목격해서 이번에 Kotlin에서 쓸 것 같은 스타일로 몇몇 부분들을 다듬었다 - 새로 알게 된 부분들을 어제에 이어서 적어보고자 한다.
배웠던/느꼈던 점
setter와 getter메서드를 명시적으로 쓰지 않아도 된다 + 생성자를 간략화할 수 있다
작년에 Java를 공부하면서 코드를 몇몇 만들어 보았는데,
public class StudentScore {
private String name;
private int scoreKorean;
private int scoreMath;
private int scoreEnglish;
}-와 같은 학생 성적 class가 있다고 하자. 이름(문자열), 국어 성적(정수), 수학 성적(정수), 영어 성적(정수) 필드가 있다. private 접근 제어자(access modifier)를 두어 객체 외부에서 임의로 필드에 직접 접근하는 - 읽고 쓰는 - 걸 막았다. 외부에서 접근하고 수정할 수 있게 만들기 위해선 getter(획득자) 메서드와 setter(설정자) 메서드를 두어 외부에서의 접근 권한을 설정할 수 있다. 가령:
public class StudentScore {
private String name;
private int scoreKorean;
private int scoreMath;
private int scoreEnglish;
// constructor
public StudentScore(String name, int scoreKorean, int scoreMath, int scoreEnglish) {
this.name = name;
this.scoreKorean = scoreKorean;
this.scoreMath = scoreMath;
this.scoreEnglish = scoreEnglish;
}
// setter 메서드
public void setName(String name){ this.name = name; }
public void setScoreKorean(int scoreKorean){ this.scoreKorean = scoreKorean; }
public void setScoreMath(int scoreMath){ this.scoreMath = scoreMath; }
public void setScoreEnglish(int scoreEnglish){ this.scoreEnglish = scoreEnglish; }
// getter 메서드
public String getName(){ return this.name; }
public int getScoreKorean(){ return this.scoreKorean; }
public int getScoreMath(){ return this.scoreMath; }
public int getScoreEnglish(){ return this.scoreEnglish; }
}처럼 get{fieldNameCamelCased} / set{fieldNameCamelCased} 이름의 틀을 두고 해당 필드의 값을 읽어들이거나 수정할 때 해당 메서드들을 사용한다. 여기서 특정 필드에 대한 쓰기/읽기 권한을 없애고 싶다면 그냥 해당 getter / setter 메서드를 지우면 된다. 혹은 public 접근 제어 속성을 protected나 default로 바꾸어 쓰기/읽기 권한의 범위를 설정할 수도 있다.
Kotlin으로 이걸 쓴다면…
class StudentScore(
var name: String,
var scoreKorean: Int,
var scoreMath: Int,
var scoreEnglish: Int
)로 저 Java 코드를 대신할 수 있다. 생성자, setter, getter 메서드를 모두 써야 했던 Java 코드와 비교해보면 확실히 간단하다!
-
기본적인
class <className> { /* fields or methods */ }의 틀에서<className>바로 옆에 괄호로 묶은property(자바의field)들을 붙인다.- 별다른 추가 함수나 프로퍼티가 없을 경우 중괄호를 생략할 수 있다.
를 통해 생성자 구현을 간략화할 수 있다(이걸
Kotlin에선primary constructor라고 부른다]). -
별다른 추가 구문이 없을 경우 프로퍼티는
public접근 제어 속성을 가진다(Java는 기본이default이다).- 기본
setter와getter를 가진다. 명시적으로 만들지 않아도 가지고 있다가, 해당 프로퍼티의 값을 읽어들이거나 값 수정을 시도할 때 이getter와setter를 부름으로써 이런 접근이 직접적이지 않게 만든다.hans.scoreMath = 90이라는 구문은hans.scoreMath에 값을 직접 씌우는 게 아니라scoreMath의setter함수를 호출하여 내부에서hans.scoreMath의 값을 바꾸는 식인 셈이다.public속성을 가지지만 위의Java코드와 비슷하게 데이터 은닉이 가능하다.
의 특성을 가진다. 만약 프로퍼티에 접근 권한을 두고 싶다면 - 예를 들어 영어 점수(
scoreEnglish)의 (외부를 통한) 쓰기 권한을 제한하고 싶다면 - 이렇게 쓰면 된다:class StudentScore { var name: String, var scoreKorean: Int, var scoreMath: Int, scoreEnglish: Int } { var scoreEnglish: Int = scoreEnglish private set }생성자에서가 아닌 클래스 본문에서 (생성자로 받은) 값으로 프로퍼티를 초기화하는 방식으로 바뀌었지만, 이렇게 하면 아래의
private set처럼getter/setter의 접근 권한을 설정할 수 있다(primary constructor안에선 할 수 없다). 심지어는 저getter와setter를 자신이 원하는 방향으로 구동하도록 바꿀 수도 있다!
… 어쩌다 보니 2개 - 생성자 구현부를 줄일 수 있다 + getter / setter 함수를 명시적으로 쓰지 않아도 된다 - 로 분리하려다가 하나로 합쳐서 쓰게 됐다. 여기서 본 Java - Kotlin 코드 비교가 어제 이야기했던 이 언어를 배워보고 싶은 이유였다. 공식 문서도 강의도 보고 하면서 새로 배우는 게 많아지는 것이 즐겁긴 한데즐 겁 다 한 편으로는 좀 걱정이 되기도 한다. 이게 “기초”편이고 “심화”편은 아직도 들어가지 않았다고 했으니까.
모르겠다, 또 어떤 새로운 사실들을 알게 될까?