자바 개발자를 위한 코틀린 입문 강의에서 9강 코틀린에서 클래스는 다루는 방법을 듣던 중 궁금한 점이 생겨 글을 작성하게되었습니다. 강의 내용에 따르면
코틀린에서는 기본적으로 부생성자보다는 default parameter를 권장한다고 하였습니다. 그리고 어쩔 수 없이 부생성자를 써야하는 경우에는 부생성자보다는 정적 팩토리 메소드를 사용을 추천해주셨습니다.
이 글은 자바에서의 생성자, 코틀린에서의 생성자에 대해 알아보고 정적 팩토리 메소드에 대해 공부하면서 정리한 글입니다.
자바에서는 아래와 같이 생성자를 만들 수 있습니다.
java
public class JavaPerson {
private String name;
private int age;
public JavaPerson(String name, int age){
this.name = name;
this.age = age;
}
}
위의 코드를 코틀린으로 변경해본다면 아래와 같이 변경할 수 있습니다.
Kotlin
class KotlinPerson(
var name : String,
var age: Int
)
만약 나이를 검증한 뒤에 객체를 생성해야할 때는 어떻게 해야할까요??
자바에서는 아래와 같이 할 수 있습니다.
java
public class JavaPerson {
private String name;
private int age;
public JavaPerson(String name, int age){
if (age <= 0){
throw new IllegalArgumentException("나이가 잘못됐습니다.");
}
this.name = name;
this.age = age;
}
}
이렇게 검증하는 로직이 필요할 때 코틀린에서는 어떻게 하는게 좋을까요? 코틀린에서는 init
키워드를 이용하여 위와 같은 검증 로직을 추가할 수 있습니다.
init
키워드는 값을 적절히 만들어주거나 validation 로직을 넣거나 하는 용도로 사용됩니다.
Kotlin
class KotlinPerson(
var name : String,
var age: Int
){
init {
if (age < 0) {
throw IllegalArgumentException("나이가 잘못됐습니다.")
}
}
}
객체를 생성하다보면 기존 생성자 이외에 추가적인 생성자가 필요할 때가 있습니다. 자바에서는 아래와 같이 생성자를 추가할 수 있습니다.
java
public class JavaPerson {
private String name;
private int age;
public JavaPerson(String name, int age){
this.name = name;
this.age = age;
}
public JavaPerson(String name){
this(name, 1);
}
}
코틀린에서는 추가 생성자를 어디에 만들어야할까요? 코틀린에서는 constructor
키워드를 이용하여 아래와 같이 추가 생성자를 만들 수 있습니다.
Kotlin
class KotlinPerson(
var name : String,
var age: Int
){
constructor(name: String): this(name, 1)
}
하지만 위에서 언급했던 것 처럼 코틀린에서는 부생성자보다는 default parameter를 권장한다고 합니다. 그냥 주 생성자에 default parameter를 넣어서 paramter를 넣어주지 않으면 기본값을 쓰게 하는 것입니다. 예시는 아래와 같습니다.
Kotlin
class KotlinPerson(
var name : String = "박창환",
var age: Int = 1,
)
하지만 부생성자가 필수적일 때는??
이때는 정적 팩토리 메소드를 사용하는 것이 좋습니다.
정적 팩토리 메소드란 객체 생성의 역할을 하는 클래스 메소드입니다.
우선 자바 코드로 확인해보겠습니다.
일반적으로 자바에서 객체를 생성할때는 아래와 같이 생성합니다.
java
class Person {}
Product product = new Product();
하지만 아래와 같이 클래스 메소드를 통해 객체를 생성할 수 있고, 이 메소드를 정적 팩토리 메소드라고 부릅니다.
java
class Person {
static of(){
return new Person();
}
}
Product product = Product.of();
유명한 책인 이펙티브 자바에서는 아래 구절과 같이 정적 팩토리 메소드 사용을 권장합니다.
생성자보다 정적 팩토리 메소드를 고려하라
정적 팩토리 메소드는 아래와 같은 장점이 있습니다.
1. 의미있는 이름을 부여할 수 있습니다.
2. 호출할 때마다 새로운 객체를 생성할 필요가 없습니다.
3. 하위 객체를 반환할 수 있습니다.
4. 생성자 로직을 깔끔하게 유지할 수 있습니다.
구체적인 예시는 정적 팩토리 메소드 정리에서 확인하실 수 있습니다.
하지만 static 키워드가 없는 코틀린에서는 어떻게 정적 팩토리 메소드를 만들 수 있을까요?
이럴 때 사용하는 것이 Companion Object(동반객체)입니다.
코틀린에서의 예시는 아래와 같습니다.
Kotlin
class KotlinPerson(
var name : String,
var age: Int,
){
companion object{
fun of(name: String, age: Int): KotlinPerson{
return KotlinPerson(name, age)
}
}
}
이렇게 companion object를 통해 of() 라는 메소드를 제공해주면 아래와 같이 인스턴스화 하지 않고 KotlinPerson 클래스 내부에 있는 메소드에 접근할 수 있게됩니다.
Kotlin
KotlinPerson.of(name = "박창환", age = 27)
자바와 코틀린에서의 생성자 그리고 팩토리 메소드 패턴에 대해 알아보았습니다. 지금까지는 추가 생성자가 필요하면 추가 생성자 코드를 작성했는데 앞으로는 정적팩토리 메소드를 활용하여 객체를 생성할 수 있도록 해야겠습니다. 감사합니다.
제가 잘못이해하고 있거나 잘못 작성한 부분이 있다면 지적, 비판, 피드백 뭐든 해주시면 감사하겠습니다!