[Kotlin] 클래스(class)
생성자
- 객체 생성시
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
이다
- public : 공개
- internal : 모듈 내부에만 공개
- 바이크 코드로 변환되면 자바에서 public으로 변환된다
- protected : 속한 클래스와 속한 클래스의 모든 하위 클래스에만 공개
- 자바와 다른점
- 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
: 런타임 시점에 할당
- cf)
-
@JvmStatic
: 자바에서 static 함수처럼 접근 가능하도록 해줌 - compaion object에 이름을 붙일 수도 있음
companion object Name {}
- 이름을 붙이지 않으면 기본 이름은
Companion
- 이름을 붙이면 명명한 이름으로 접근 가능
Person person = Person.Companion.newBaby("europa")