자바와 코틀린의 생성자, 정적팩토리 메소드

모지리 개발자·2022년 11월 30일
3

Kotlin

목록 보기
4/5

Intro

자바 개발자를 위한 코틀린 입문 강의에서 9강 코틀린에서 클래스는 다루는 방법을 듣던 중 궁금한 점이 생겨 글을 작성하게되었습니다. 강의 내용에 따르면

코틀린에서는 기본적으로 부생성자보다는 default parameter를 권장한다고 하였습니다. 그리고 어쩔 수 없이 부생성자를 써야하는 경우에는 부생성자보다는 정적 팩토리 메소드를 사용을 추천해주셨습니다.

이 글은 자바에서의 생성자, 코틀린에서의 생성자에 대해 알아보고 정적 팩토리 메소드에 대해 공부하면서 정리한 글입니다.

Java와 Kotlin에서의 생성자

자바에서는 아래와 같이 생성자를 만들 수 있습니다.

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)

결론

자바와 코틀린에서의 생성자 그리고 팩토리 메소드 패턴에 대해 알아보았습니다. 지금까지는 추가 생성자가 필요하면 추가 생성자 코드를 작성했는데 앞으로는 정적팩토리 메소드를 활용하여 객체를 생성할 수 있도록 해야겠습니다. 감사합니다.

제가 잘못이해하고 있거나 잘못 작성한 부분이 있다면 지적, 비판, 피드백 뭐든 해주시면 감사하겠습니다!

profile
항상 부족하다 생각하며 발전하겠습니다.

0개의 댓글