kotlin 정리 3

mangyun·2021년 11월 18일

kotlin

목록 보기
3/4

클래스

클래스 선언 - Kotlin

// 멤버 프로퍼티(변수)와 생성자를 동시에 선언
class SimpleClass(val name: String, var address: String, var age: Int = 41)

kotlin 클래스의 기본생성자는 클래스명 바로 옆 “()” 구문이다. 기본 생성자의 매개변수 선언을 val name: String 하면 멤버 프로퍼티(변수)선언과 기본생성자 매개변수 선언을 동시에 한 것이다.

클래스 선언 - Java

public class SimpleClass {
    private String name;
    private String address;
    private Integer age

    public SimpleClass(String name, String address, Integer age) {
        this.name = name;
        this.address = address
        this.age = age
    }

    public String getName() {
        return name;
    }

    public String getAddress() {
        return address;
    }

    public Integer getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

Kotlin 클래스 선언이 위 Java 코드와 동일하다.

클래스 멤버 프로퍼티와 생성자 파라메터 동시 선언

// var name: String <= var/val 를 붙이면 
// 생성자 매개변수 선언과 동시에 멤버 프로퍼티(변수)를 선언한 것과 같다
class BasicClass(var name: String, var address: String) {
    // var name:String <= 한 것 과 같다
    ...
}

클래스 멤버 프로퍼티와 생성자 파라메터 각각 선언

// name: String <= var/val 를 붙이지 않으면 생성자 매개변수만 선언 한 것 이다.
// 그래서 멤버 프로퍼티(변수)를 꼭 선언 해야한다.
class BasicClass(name: String, address: String) {
    var name:String
    var address:String

    ...
}

위 경우에는 반드시 기본생성자의 초기화 init블럭이 있어야 한다.

클래스 기본생성자의 초기화 init 블럭

**class BasicClass(var name: String, var address: String)** 처럼 프로퍼티 선언과 생성자 매개변수 동시 선언 하지 않으면 아래 예제 처럼 멤버 프로퍼티 선언과 함께 init블럭을 통하여 멤버프로퍼티의 초기화도 해주어야 한다.

class BasicClass(name: String, address: String, age: Int) {
    // 프로퍼티선언과 동시에 생성자 파라메터로 값 설정이 가능하며 초기화 구문 까지 포함 된 것이다.
    var name: String = name 
    var address: String
    var age: Int

    init {
        this.address = address
        this.age = age
    }
}

name 프로퍼티는 var name: String = name 선언과 동시에 초기화 구문 까지 함께 기술 하였기 때문에 init 블럭에서 초기화 구분이 제외 되었다.

코틀린 init을 Java로 표현

public class BasicClass {
    private String name;
    private String address;
    private Integer age

    public BasicClass(String name, String address, Intger age) {
        this.name = name;
        this.address = address;
        this.age = age;
    }
}

클래스 기본생성자의 초기화 init 블럭을 Java 코드로 표현하면 위와 같다.

클래스와 접근제한자

코들린의 프로퍼티란?

  • 코틀린에서 프로퍼티란 클래스의 멤버 변수를 말하는데 코틀린에서 멤버 변수는 단순히 var name:String 으로 선언 되어 변수만 선언된 것 같지만 setter/getter를 따로 선언 하지 않아도 기본적으로 생성되며 변수 + setter + getter 프로퍼티라고 부른다.
    하지만 person.name 처럼 사용하면 person.getName() 처럼 getter를 사용하지 않는 것 처럼 보이지만 사실은 person.name 값을 가져오면 내부적으로 getter를 사용 한 것이다.

클래스의 프로퍼티와 override getter/setter

class BasicClass(name: String, address: String, age: Int) {
    var name: String 
    var address: String
        get() = "$field 특별시"
        set(address) {
            field = "$address 특별시"
        }
    var age: Int

    init {
        this.name = name 
        this.address = address
        this.age = age
    }
}

val basicClass = BasicClass("김찬정", "서울", 10)
println(basicClass.address) // 서울 특별시 로 출력 됨
basicClass.address = "서울" // 서울 특별시 로 변경됨

기본적으로 getter/setter가 제공되지만 예제 처럼 override 한 것이다.
basicClass.getAddress(), basicClass.setAddress(“서울”) 처럼 사용해야 될 것 같지만 변수를 바로 다루는 듯 사용하며 실제로 getter/setter가 동작 한다.

코들린의 public 프로퍼티의 변수는 public인가?

// 아래 처럼 선언하면 
class BasicClass(name:String) {
    var name:String // public 생략됨
    private var age: Int // 프로퍼티를 private로 선언하면
}

코틀린의 접근제한자는 기본적으로 멤버 프로퍼티(변수+getter+setter)에 대한접근 제한 자이다. public var name:String 은 name라는 변수는 private로 직접 접근이 불가능하며 기본으로 제공되는 getter/setter에 의해서 접근이 되는 것이고 getter/setter가 제공됨으로써 name프로퍼티는 public인 것 이다. 아래 예제를 보자 JAVA 코드로 변환 하면 실제로는 아래와 같다

public class BasicClass {
    private String name;
    private Integer age;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
private var age: Int 프로퍼티를 private로 선언했기 때문에 Java 코드로 본다면 getter/setter가 제공 되지 않아 외부에서 접근 자체가 불가한 것이다.

생성자 오버로딩(여러개의 생성자)

class OverLoadingConstructor(name: String) {
    // init 블럭 그리고 constructor에 초기화 구문이 둘다 들어가 있으므로 초기화 필요 없다.
    var name: String
    lateinit var address: String
    // primitive type 프로퍼티는 사용 불가능 하기 때문에 0값으로 라도 초기화 해야한다.
    var age: Int = 0

    init {
        this.name = name
    }

    constructor(name: String, address: String, age: Int) : this(name) {
        this.name = name
        this.address = address
        this.age = age
    }
}

// 다음과 같이 생성자가 제공된다.
val overLoadingConstructor = OverLoadingConstructor("김찬정")
val overLoadingConstructor2 = OverLoadingConstructor("김찬정", "서울", 20)

lateinit 이란 멤버프로퍼티의 값 초기화를 지연하는 키워드이며 다음과 같은 특징이 있다.

  • var(mutable) 프로퍼티만 사용 가능
  • non-null 프로퍼티만 사용 가능
  • 커스텀 getter/setter가 없는 프로퍼티만 사용 가능
  • primitive type 프로퍼티는 사용 불가능
  • 클래스 생성자에서 사용 불가능
  • 로컬 변수로 사용 불가능

Init 블럭 없는 생성자 오버로딩

class OverLoadingConstructorWithoutInit {
    var name: String
    var address: String = ""
    var age: Int = 0

    constructor(name: String) {
        this.name = name
    }

    constructor(name: String, address: String, age: Int) {
        this.name = name
        this.address = address
        this.age = age
    }
}
// 다음과 같이 생성자가 제공된다.
val overLoadingConstructor = OverLoadingConstructor("김찬정")
val overLoadingConstructor2 = OverLoadingConstructor("김찬정", "서울", 20)

클래스 선언시 클래스명 옆에 기본생성자를 선언하지 않고 constructor를 선언한다. 그렇게 되면 init 블럭도 필요없어진다.

profile
기억보다는 기록을 하자.

0개의 댓글