이제 일주일차인데.. 이미 한달 한 것 같은 느낌쓰 ~ ^^
일단 목요일에 페어프로그래밍 step1을 PR을 보낸 상태이고, 난 아직 리뷰를 받지 못했다!
금요일 오전에 바로 자동차 경주에 대한 전체적인 피드백을 받을 수 있다.
오늘 피드백을 주신 분은 Jason(백에서 안드로 오신 그 분...)이었다. 전체 피드백을 항상 제이슨이 해주는지는 아직 잘 모르겠다.
이름을 지을 때는 규칙들이 몇가지 있는데, 프리코스 시절 검색했던 것이므로 넘어 가겠다.
변수 명을 지을 때는 아래 Car와 같은 경우는 넘어오는 인자가 무작위인지 아닌지 알 필요가 없으므로 randomNumber 보다는 number을 사용하는 것이 좋다.
fun move(randomNumber: Int) {
if (randomNumber >= FORWARD_NUMBER) position++
}
자료에 달려있던 - 효과적인 이름짓기
나는 아직 제대로 읽어보지 않았지만 혹시나 필요하다면 읽는 것도 좋다.
제이슨이 추천해준 - grep.app
만약 여러 이름 중 고민중이라면 여기서 많이 각 이름이 사용된 빈도를 검색해 볼 수 있다.
클래스는 프로퍼티, 초기화 블록, 부 생성자, 함수, 동반 객체 순으로 작성한다.
(이 내용은 예전 포스팅에서 다룬 적이 있다. 잘 찾아보면 더 자세히 알 수 있다.)
주 생성자 : primary constructor
클래스 이름 뒤에 오는 괄호로 둘러싸인 코드.
주 생성자는 제한적이기 때문에 별도의 코드를 포함할 수 없으므로 초기화 블럭이 필요하다. 필요하다면 클래스 안에 여러 초기화 블럭을 선언 할 수 있다.
class Car(val name: String) {
var position: Int
init {
position = 0
}
}
초기화 블럭은 프로퍼티 선언에 포함시킬 수 있어 생략이 가능하다.
class Car(val name: String) {
var position: Int = 0
}
클래스 인스턴스를 생성 시 파라미터 목록이 다른 생성 방법이 여럿 존재하는 경우에는 부생성자를 둘 수 있다. 여기서는 부 생성자가 주 생성자를 호출하도록 한다.
class Car(val name: String, var position: Int) {
constructor(name: String) : this(name, 0)
}
인자에 대한 기본 값을 제공하기 위해 부생성자를 만드는 대신 매개 변수의 기본 값을 사용할 수도 있다.
class Car(val name: String, var position: Int = 0)
프로퍼티의 getter 함수를 노출하면서 setter에 대한 접근을 제한하기 위해서는 setter 함수를 private으로 지정해주어야 한다.
class Car(val name: String) {
var position: Int = 0
private set
}
❔ 함수 VS 메서드
코틀린의 기본적인 함수는 fun 키워드로 시작한다.
메서드는 클래스와 연결된 함수를 의미한다. 멤버 함수 (클래스 내에 정의된 함수)는 해당 클래스와 연결되어 있으므로 메서드이다. 메서드를 호출하기 위해서는 클래스 인스턴스가 있어야하며, 이를 활용해서 참조해야한다.
❔ 프로퍼티 VS 필트 - 참고
프로퍼티 = 필드 (실제로 데이터가 저장되는 공간) + Getter (저장된 값을 읽으려고 할 때 호출되는 함수) + Setter (값을 저장하려고 할 때 호출되는 함수)
-> 코틀린에서는 자동 게터/세터
생성자 몇 개의 인자들을 전달받아 이들을 이용해서 어떤 일을 수행한 후, 객체가 자신의 의무를 수행할 수 있도록 준비시킨다. 응집도가 높고 견고한 클래스에는 적은 수의 메서드와 상대적으로 더 많은 수의 생성자가 존재한다.
생성자의 주된 임무 : 제공된 인자를 사용해서 캡슐화된 프로퍼티를 초기화
-> 메서드의 수가 많을수록 단일 책임 원칙을 위반하지만, 생성자의 수가 많아질수록 클라이언트가 클래스를 더 유연하게 사용할 수 있다.
상수 이름은 밑줄로 구분된 대문자를 사용한다.
const val DEFAULT_POSITION: Int = 0
클래스나 함수와 마찬가지로 최상위 수준에 프로퍼티를 정의할 수 있다. 이런 경우 프로퍼티는 전역 변수나 상수와 비슷한 역할을 한다. 최상위 프로퍼티의 값은 정적 필드에 저장된다. 이런 프로퍼티에 최상위 가시성을 지정할 수 있으며, 임포트 디렉티브에서 최상위 프로퍼티를 임포트할 수 도 있다.
private const val DEFAULT_POSITION = 0
class Car(val name: String, positon: Int = DEFAULT_POSITION)
어떤 클래스에 인스턴스가 오직 하나만 존재하게 보장하는 싱글턴 패턴을 내장하고 있다.
class Car(val name: String, positon: Int = DEFAULT_POSITION) {
companion object {
private const val DEFAULT_POSITION = 0
// 기본 자료형 외에는 const 키워드 사용 불가
val DEFAULT_CAR = Car("jason")
}
}
❔ 최상위 수준 vs 동반객체, 각각의 장단점은 무엇인가요?
-> ... 몰라요..
아래 3가지 조건을 충족하면 1급 시민이다.
객체 지향 언어인 Java에서는 모든 코드를 클래스의 메서드로 작성해야 한다는 사실을 알고 있다. 하지만 실전에서는 어느 한 클래스에 포함시키기 어려운 코드가 많이 생긴다. 일부 연산에는 비슷하게 중요한 역할을 하는 클래스가 둘 이상 있을 수도 있다. 그 결과 다양한 정적 메서드를 모아두는 역할만 담당하며, 특별한 상태나 인스턴스 메서드는 없는 클래스가 생겨난다.
코틀린에서는 이런 무의미한 유틸 클래스가 필요 없다. 대신 함수를 파일의 최상위 수준에 위치시키면 된다.
코틀린에서는 프로그래머 대신 컴파일러가 캐스팅을 해 준다. 어떤 변수가 원하는 타입인지 검사하고 나면 굳이 변수를 원하는 타입으로 캐스팅하지 않아도 마치 처음부터 그 변수가 원하는 타입으로 선언된 것처럼 사용할 수 있다. 하지만 실제로는 컴파일러가 캐스팅을 수행해 주며 이를 스마트 캐스트(smart cast) 라고 부른다.
require (인자로 받은 값의 유효성 검사) 값을 만족하지 않으면 IllgealArgumentException을 발생
ex)
check (현재 객체의 인스턴스 상태, 구체적인 조건) 값을 만족하지 않으면 IllegalStateException을 발생
ex)
다시 찾아볼 것
👻 최상위 수준 vs 동반객체, 각각의 장단점은 무엇인가요?
👻 익명 클래스 : 즉석 생성 open 키워드 사용