생성자

  • 객체 생성시 new 키워드 없음
class Person {
  var firstName: String = ""
  var familyName: String = ""
  var age: Int = 0

  fun fullName() = "$firstname $familyName"

  fun showMe() {
    println("${fullName()} , $age")
  }
}

var person = Person()
person.firstName = "John"
person.familyname = "Doe"
person.age = 25
person.showMe()
  • 생성자 이용
    • 클래스 헤더의 파라미터 목록을 주생성자(primary constructor) 선언 이라고 한다
    • 주생성자 파라미터는 프로퍼티 초기화나 init 블록 밖에서 사용할수 없다
    • init 블록을 통해 클래스 초기화시 실행시킬 로직을 만들 수 있음
class Person2(firstName: String, familyName: String) {
  var fullName = "$firstName $familyName"

  // 초기화 로직
  init {
    println("Created new Person instance : $fullName")
  }
}

var person2 = Person2("Johe", "Doe")
println(person2.fullName)

class Person3(fullName: String) {
  val firstName: String
  val familyName: String

  init {
    val names = fullName.split(" ")
    firstName = names[0]
    familyName = names[1]
  }
}

부생성자 (비권장)

  • 주생성자로 충분치 않을 경우 부생성자를 사용할 수 있음
  • constructor 사용
class Person {
  var firstName: String
  var familyName: String

  fun fullName() = "$firstname $familyName"

  constructor(firstName: String, familyName: String) {
    this.firstName = firstName
    this.familyName = familyName
  }

  constructor(fullName: String) {
    val names = fullName.split(" ")
    firstName = names[0]
    familyName = names[1]
  }
}
  • 하지만, 코틀린에서는 부생성자보다는 default 파라미터를 권장한다
  • Converting의 경우에는 부생성자보자는 정적 팩토리 메서드를 권장한다
class Person {
  val name: String = "europa"
  val age: Int = 1
}

Getter, Setter

  • 코틀린은 클래스 선언 방식에 따라 필드의 Getter, Setter를 자동으로 만들어 준다
클래스 선언 Getter 생성 Setter 생성 유형
class Person(name: String) X X 생성자 파라미터
class Person(val name: String) O X 속성
class Person(var name: String) O O 속성
// 1. class Person(name: String)
var person = Person("europa")
println(person.name)   // error!!

// 2. class Person(val name: String)
var person = Person("europa")
println(person.name)
person.name = "racheal"   // error!!

// 3. class Person(var name: String)
var person = Person("europa")
println(person.name)
person.name = "racheal"

커스텀 Getter, Setter

  • Getter : 원하는 필드 아래에 get() 정의
  • Setter : 원하는 필드 아래에 set(value) { } 정의
    • value : 세터를 통해 할당받은 값
    • field : 해당 필드를 지칭 (무한루프를 막기위해 존재 )
class Person(val firstName: String, val familyName: String) {
  var fullName: String
    get() {
      return "$firstName $familyName"
    }
    set(value) {
      field = value
    }
}

접근제어자

  • 코틀린에는 package 개념을 접근제어자에 사용하지 않기 때문에 package-priavte가 존재하지 않음
  • 자바는 default가 package-priavte 이지만 코틀린은 public 이다
  1. public : 공개
  2. internal : 모듈 내부에만 공개
    • 바이크 코드로 변환되면 자바에서 public으로 변환된다
  3. protected : 속한 클래스와 속한 클래스의 모든 하위 클래스에만 공개
    • 자바와 다른점
  4. private : 클래스 내부에만 공개

프로퍼티

  • 생성자에 접근제어자를 지정하려면 constructor 생략이 불가능하다
class Car internal constructor( // 생성자가 internal
  internal val name : String,   // name의 getter가 internal
  _price : Int
) {
  var price : Int = _price      // price의 setter는 public
    private get                 // price의 getter가 private
}

타입 캐스팅

  • v is Type : boolean 리턴
  • v as Type : v가 Type이면 타입 캐스팅, 아니면 NPE
  • v as? Type : v가 Type이면 타입 캐스팅, 아니거나 null이면 null 리턴
public static void printAgeIfPerson(Object obj) {
  if (obj instanceof Person) {
    Person person = (Person) obj;
    System.out.println(person.getAge());
  }
}

↓↓↓↓↓

fun printAgeIfPerson(obj : Any) {
  if (obj is Person) {
    val person = obj as person
    println(person.age)
  }
}
  • 동일성, 동등성

1. 동일성 : 같은 객체인지 비교

  • Java : == / Kotlin : ===

2. 동등성 : 값이 같은지 비교

  • Java : equals() / Kotlin : ==
  • 코틀린은 ==을 사용하면 내부에서 equals()를 호출한다

상속

  • : 사용
public abstract class Animal {
  protected final String species;
  protected final int legCount;

  public Animal(String species, int legCount) {
    this.species = species;
    this.legCount = legCount;
  }

  abstract public void move();

  // getter
}

↓↓↓

abstract class Animal(
  protected val species: String,
  protected open val legCount: Int
) {

  abstract fun move()
}
  • open : 하위 클래스에서 해당 프로퍼티를 override 하기 위해서 필요한 키워드
    • 코틀린은 final이 default이기 때문에 오버라이드를 위해 해당 키워드를 사용해야 한다
    • 이 예제에서 Penguin에서 오버라이딩 하고있음
public class Cat extends Animal {

  public Cat(String species) {
    super(species, 4);
  }
  @Override
  public void move() {
    System.out.println("cat move");
  }
}

↓↓↓

class Cat(
  species: String
) : Animal(species, 4) {

  override fun move() {
    println("cat move");
  }
}
public class Penguin extends Animal {
  protected final int wingCount;

  public Penguin(String species) {
    super(species, 2);
    this.wingCount = 2;
  }
  @Override
  public void move() {
    System.out.println("penguin move");
  }
  @Override
  public int getLegCount() {
    return super.legCount + this.wingCount;
  }
}

↓↓↓

class Penguin(
  species: String
) : Animal(species, 2), Flyable {

  private val wingCount : Int = 2

  override fun move() {
    println("penguin move");
  }

  override val legCount : Int
    get() = super.legCount + this.wingCount
}

인터페이스

  • 코틀린의 인터페이스를 프로퍼티를 갖을 수 있다
public interface Flyable {
  void fly();

  default void act() {
    System.out.println("shake the wings");
  }
}

↓↓↓

interface Flyable {
  fun fly()

  fun act() {
    println("shake the wings");
  }
}

Static

  • 코틀린에는 static 키워드가 존재하지 않는다
    • companion object 사용 (동행 객체) : 클래스와 동행하는 Object라는 뜻
public class Person {
  private static final int MIN_AGE = 1;

  private String name;
  private int age;

  private Person(String name, int age) {
    this.name = name;
    this.age = age;
  };

  public static Person newBaby(String name) {
      return new Person(name, MIN_AGE);
  }
}

↓↓↓

class Person private constructor(
  private val name : String,
  private val age : Int
) {
  
  @JvmStatic      // 자바에서 static 함수처럼 접근 가능하도록 해줌
  companion object {
    private const val MIN_AGE = 1;
    fun newBaby(name : String) Person {
      return Person(name, MIN_AGE)
    }
  }
}
  • const : 컴파일 시점에 변수 할당
    • cf) val : 런타임 시점에 할당
  • @JvmStatic : 자바에서 static 함수처럼 접근 가능하도록 해줌

  • compaion object에 이름을 붙일 수도 있음
    • companion object Name {}
    • 이름을 붙이지 않으면 기본 이름은 Companion
    • 이름을 붙이면 명명한 이름으로 접근 가능
Person person = Person.Companion.newBaby("europa")