파게로그

[OOP] Constructors 본문

콤퓨타 왕기초/Kotlin

[OOP] Constructors

파게 2021. 6. 10. 15:02

Constructors

생성자는 클래스 속성을 초기화하는 데 있어서 정확한 방법이다. 생성자는, 특별한 멤버 함수로서, 객체가 처음 생성될 때(instantiated) 호출된다. 그러나 Kotlin에서 작동하는 방법은 다소 다르다. Kotlin에서는 두 가지의 생성자가 있다.

 

▪ Primary constructor

consise way to initialize a class

▪ Secondary constructor

allows you to put additional initialization logic

 

Primary Constructor

primary constructor는 클래스 헤더의 일부이다.

 

class Person(val firstName: String, var age: Int) {
    // class body
}

 

 

 

일단, 이렇게 헤더에서 바로 멤버 변수들을 선언할 수 있다.

fun main(args: Array<String>) {
    var person = Person("Peter", 25)
    person.introduce()
}

class Person(var name: String, var age: Int) {
    fun introduce() {
        println("My name is $name. I am $age years old.")
    }
}

 

그리고 아래와 같이 생성자를 만들 수도 있는데, 이 때에는 멤버 변수의 이름과 파라미터의 이름을 다르게 설정할 수 있다.

class Person(name: String, age: Int) {
    var name = name
    var age = age

    fun introduce() {
        println("My name is $name. I am $age years old.")
    }
}

 

Initializer Blocks

primary constructor는 제한된 문법을 가지고 있어서 모든 코드를 포함할 수 있는 것은 아니다. properties를 초기화하기 위한 코드뿐만 아니라, initilization 코드 또한 삽입하기 위해서는, initializer block이 사용된다. initializer block에는 init 키워드를 붙인다. 

 

fun main(args: Array<String>) {
    val student = Student("mary", 71, 74, 73)
}

class Student(name: String, val kor: Int, val eng: Int, val math: Int) {
    val firstName: String
    val avg: Double

    init {
        firstName = name.capitalize()
        avg = (kor + eng + math) / 3.0
        println("Object {firstName=%s, avg=%.3f} is created.".format(firstName, avg))
    }
}

 

실행결과는 다음과 같다.

Object {firstName=Mary, avg=72.667} is created.

 

위 코드와 아래 코드는 동일한 기능을 수행한다.

 

fun main(args: Array<String>) {
    val student = Student("mary", 71, 74, 73)
}

class Student(name: String, val kor: Int, val eng: Int, val math: Int) {
    val firstName: String = name.capitalize()
    val avg: Double = (kor + eng + math) / 3.0

    init {
        println("Object {firstName=%s, avg=%.3f} is created.".format(firstName, avg))
    }
}

 

대부분의 경우, 파라미터와 멤버 변수의 이름을 구분하고자 할 때, 아래와 같이 언더스코어를 많이 사용한다.

class Person(_firstName: String, _age: Int) {
    val firstName = _firstName.capitalize()
    var age = _age

    init {
        // ...
    }
}

 

 

Default Value in Primary Constructor

생성자의 파라미터에도 기본값을 제공할 수 있으며, 이는 함수에서 기본값을 설정하는 것과 비슷하다.

fun main(args: Array<String>) {
    val building1 = Building()
    var building2 = Building("dongbo")
    var building3 = Building(grossFloorArea = 18522.5351);
    var building4 = Building("dongbo", 18522.5351)
}

class Building(var name: String = "unknown", val grossFloorArea: Double = 0.0) {
    init {
        name = name.capitalize();
        println("Building's name is %s, gross floor area is %.3f.".format(name, grossFloorArea))
    }
}

 

실행결과는 다음과 같다.

Building's name is Unknown, gross floor area is 0.000.
Building's name is Dongbo, gross floor area is 0.000.
Building's name is Unknown, gross floor area is 18522.535.
Building's name is Dongbo, gross floor area is 18522.535.

 

Secondary Constructor

클래스는 하나 또는 하나보다 많은 secondary constructor를 가질 수 있다. 이들은 constructor 키워드를 사용한다.

secondary constructors는 그렇게 보편적이지는 않다. 대부분의 사용은, 클래스를 서로 다른 방법으로 초기화하는, 복수의 생성자를 제공하는 클래스를 상속받고자 할 때 사용된다.

 

class Log {
    constructor(data: String) {
        // ...
    }
    
    constructor(data: String, numOfData: Int) {
        // ...
    }
}

 

Log는 2개의 secondary constructors를 가지며, primary constructor는 가지고 있지 않다. 이 클래스를 다음과 같이 상속받을 수 있다.

 

open class Log {
    constructor(data: String) {
        // ...
    }

    constructor(data: String, numberOfData: Int) {
        // ...
    }
}

class AuthLog: Log {
    constructor(data: String): super(data) {
        // ...
    }

    constructor(data: String, numberOfData: Int): super(data, numberOfData) {
        // ...
    }
}

class ErrorLog: Log {
    constructor(data: String): this(data, 10) {
        // ...
    }

    constructor(data: String, numberOfData: Int): super(data, numberOfData) {
        // ...
    }
}

 

this()와 super()도 모두 사용할 수 있다.

 

참고로, primary constructor가 없을 경우, secondary constructor는 base class를 반드시 초기화하거나, 위의 예시처럼 다른 생성자에게 초기화를 위임해야 한다.

'콤퓨타 왕기초 > Kotlin' 카테고리의 다른 글

[OOP] inheritance  (0) 2021.06.12
[OOP] Getters and Setters  (0) 2021.06.11
[OOP] OOP, Class and Objects  (0) 2021.06.10
[Basic] Tail Call, Tail Recursion  (0) 2021.06.10
[Basic] Default arguments and Named arguments  (0) 2021.06.09
Comments