https://github.com/leechGamer/kotlin/commits/main/4
코틀린 클래스의 기본적인 구조
class test {
private val a: Int
init{
println("test!")
}
private val b: Int
fun isTest (): Boolean = false
}
자바 클래스와의 차이
- 코틀린은 클라이언트의 코드를 바꾸지 않아도 프로퍼티의 구현을 바꿀 수 있다.
- 코틀린은 class 안에 getter/setter를 제공함으로써 자바처럼 get으로 시작하는 함수를 새로 만들지 않아도 된다.
class Person(private var _name: String) {
val name: String
get() = _name.toUpperCase() // 커스텀 게터를 추가하여 소문자로 입력된 이름을 대문자로 반환
var age: Int = 0
set(value) {
field = if (value >= 0) value else 0 // 커스텀 세터를 추가하여 음수로 설정되는 나이를 0으로 제한
}
}
주생성자란 무엇인가?
class MyClass {
private val firstField: String = "First Field"
private val secondField: Int
init {
secondField = 42
}
private val thirdField: Boolean = true
}
부생성자란 무엇인가? 클래스에 어떤 생성자(또는 생성자들)를 포함시킬지와 주생성자 외에 부생성자가 더 필요할지를 어떻게 결정하는가?
- 코틀린의 부 생성자(Secondary Constructor)는 클래스에 추가적인 생성 방법을 제공하는 생성자를 의미한다. 이는 클래스가 다양한 매개변수를 통해 생성될 수 있도록 하는데 유용합니다. 부 생성자는 constructor 키워드를 사용해 선언.
class Person(val name: String) {
var age: Int = 0
constructor(name: String, age: Int) : this(name) {
this.age = age
}
}
class Person (private val a: Integer) {
inner class possesion() {
fun getOwner(): String = this@Person.a // 접근 됨
}
}
class Possesion(val person:Person) {
person.a // 접근 안됨
}
fun someFunction() {
class LocalClass {
fun sayHello() {
println("Hello from the local class!")
}
}
val localInstance = LocalClass()
localInstance.sayHello()
}
someFunction() // 이 함수를 호출하면 "Hello from the local class!"를 출력합니다.
private
또는 final
로만 선언될 수 있다. private
접근 제한자를 사용하면 해당 클래스는 외부로부터 완전히 은닉되고, final
키워드를 사용하면 상속을 방지하여 클래스의 확장을 막을 수 있다.class Example {
var counter = 0
set(value) {
if (value >= 0) {
field = value
}
}
}
get
과 set
키워드를 사용하여 접근자를 정의하고, 자바는 get
과 set
으로 시작하는 메서드를 작성합니다.읽기 전용 프로퍼티
커스텀 getter을 정의해서 사용하면 된다. 클래스 내부에서만 값을 변경할 수 있게 private으로 선언한다.
import java.util.*
class Person(name: String) {
private var _name: String = name
val name: String
get() = _name
}
lazy 프로퍼티를 사용해 지연 계산을 달성하는 방법은 무엇인가? lazy와 lateinit 프로퍼티를 비교해보라
이 둘의 가장 큰 차이는 외부에서 값을 주입하는지 (lateinit) 내부에서 주입하는지 (lazy)에 따라서 나눌 수 있다.
object
키워드를 사용하여 객체 선언을 할 수 있다. 객체 선언은 전역 싱글턴 인스턴스를 생성하는 데 사용된다.object Singleton {
fun doSomething() {
println("Singleton doing something")
}
}
위 코드에서 Singleton
객체는 전역 싱글턴 인스턴스이다. 이를 사용하려면 다음과 같이 호출하면 된다.
Singleton.doSomething()
객체 선언과 자바의 전통적인 싱글턴 구현 패턴을 비교하면 다음과 같다:
object
키워드를 사용하여 객체 선언을 직접적으로 생성할 수 있다. 반면에 자바에서는 전통적인 싱글턴 구현 패턴을 사용해야 한다.이와 대조적으로, 자바에서는 싱글턴 패턴을 구현하기 위해 더 많은 코드를 작성해야 한다. 자바에서는 보통 private 생성자와 static 메소드를 사용하여 싱글턴 패턴을 구현한다.
public class Singleton {
private static Singleton instance;
public static String info = "I'm a singleton object";
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
이 경우에는 Singleton.getInstance()
를 통해 싱글턴 인스턴스에 접근해야 한다.
따라서 코틀린의 객체 선언은 자바의 싱글턴 패턴 구현보다 훨씬 간결하며, 코드의 가독성과 효율성을 높여준다.
class test {
private a :Int
companion object {
fun check() {
test.a
}
}
}
object test2 {
fun check() {
test.a // error
}
}
코틀린 동반 객체 (companion object)와 자바의 static 내포 객체를 비교하라.
interface A
class Test(a:Int) {
companion object:Runnable {
override fun run() {}
}
}
class TestA(a:Int) {
companion object:Runnable {
override fun run() {}
}
}
object Test2 {
fun check(runnable: Runnable) {}
}
fun main() {
Test2.check(Test) // 이렇게만 넘겨도 됨 암묵적으로 Test.Companion의 약자
Test2.check(TestA) // 그래서 클래스 간 상속관계가 없음에도 class들의 companion에만 동시성을 부여할 수 있다.
}
위 코드에서 본 것처럼 companion static 수준의 인터페이스를 만들 수 있다.
자바에서의 static 내포 객체의 경우 공통점을 만들어 낼 수 없다.
익명클래스는 어떠한 형이라고 보면 된다.
함수 scope 안에서만 유효하기 때문에 한번만 쓸거면 익명클래스로 사용해도 충분하다 하지만 재활용되어야 한다면 class를 사용하는 것이 낫다.
fun main() {
val o = object { // 익명 객체 타입이 추론된다.
val x = readLine()!!.toInt()
val y = readLine()!!.toInt()
}
println(o.x + o.y)
}