본문 바로가기

kotlin

[Kotlin] parameter vs property, Constructor parameter is never used as a property

코틀린으로 개발 중 아래와 같은 경고를 보게 됐다.

constructor parameter is never used as a property

자바에서는 클래스 내부에서 프로퍼티와 생성자를 각각 따로 정의하고, 생성자 내부에서 프로퍼티를 값을 초기화 해주는 코드를 직접 구현하기 때문에 생성자 파라미터와 프로퍼티 개념이 헷갈릴 일이 없다. 그런데 코틀린에서는 주생성자와 프로퍼티(멤버함수) 정의를 한 번에 할 수 있다보니, 생각없이 단순 파라미터를 프로퍼티로 정의하고 갑자기 뜬 경고에 당황했다. 당황한게 창피해서 정리해본다.

parameter

우선 parameter는 매개변수로 함수나 생성자에 전달하는 값을 의미한다.

fun printName(name: Sting) {
	println(name)
}

class Student(name: String) {
	...
}

위 예시에서 함수 printName과 클래스 Student 각각에 전달된 name이 바로 파라미터다.

property

property는 함수 내부에 만드는 변수, a.k.a 멤버변수를 뜻한다. 

class Student {
	
    String name; // property
    
    public Student (String name) { // parameter
    	this.name = name;
    }
}

익숙한 자바 코드로 예를 들자면 위 Student 클래스에서 name이 바로 클래스의 프로퍼티, 멤버변수이다. 생성자에서 프로퍼티 name의 값을 초기화 해줄 때, 생성자의 파라미터 name을 클래스의 프로퍼티 this.name의 값으로 배정해주는 것이다.

위와 같은 java코드를 kotlin으로 작성하면서, 아래와 같이 점점 코드가 간단해지면서 마치 property와 parameter의 차이가 앞 키워드 val의 유무인 것처럼 보여지게 됐다.

// 주생성자 바로 정의
class Student(_name: String){
    val name = _name
}

// 주생성자 초기화 코드 생략
class Studnet(val name: String){
}

생성자 parameter가 단순히 parameter로만 사용되는 경우

전달받은 생성자의 parameter는 클래스 내부에서 사용할 수 있다. 그러나 메소드 내부에서는 사용이 불가능하다. 메소드(멤버함수)에게 공유가능한 클래스의 자원은 property(멤버함수) 뿐이다.

class User (val name: String, yearOfBirth: Int) {
	
    val age = YEAR_OF_NOW - yearOfBirth
    
    fun printAge() {
    	println(yearOfBirth) // Error
        println(age)
    }
}

위 코드에서 yearOfBirth는 parameter이고, age는 프로퍼티이다. 클래스의 생성자가 아닌 내부에서 파라미터를 통해 프로퍼티 값을 지정할 수 있다.

[Spring] parameter도 의존성 주입이 되나요?

스프링에서 사용하는 생성자 주입 방법은 parameter에 주입하는 것이다. 대체로 의존성 주입받은 bean을 property로 두고, 멤버함수 내부에서 호출하기 때문에 property로 사용하는 것을 많이 봐왔지만, 단순 파라미터로 사용하더라도 의존성이 주입된다.

import org.springframework.stereotype.Component
import org.springframework.stereotype.Repository
import org.springframework.stereotype.Service

@Service
class OrderService (val orderRepository: OrderRepository, address: Address) {

    val destination = address.getDestination()

    fun createOrder() {
        orderRepository.save(destination)
    }
}

@Repository
class OrderRepository {
    fun save(destination: String) {
    	// (생략)
    }
}

@Component
class Address {
    fun getDestination(): String {
   	// (생략)
    }
}

위 코드에서 Address는 address라는 파라미터에 잘 주입됐지만, property로는 사용하지 않고 단순 parameter로만 사용했다.

만약 address를 property로 설정했다면 위와 같은 안내문구를 볼 수 있다. (해당 안내문구가 경고로 뜨는지, 단순 warning으로 뜨는지는 intellij의 설정에 따라 다르다.)

반응형