앱 개발/Kotlin

[Kotlin] 코틀린 기본 5 (class, 다형성(상속), 생성자)

cha430 2026. 2. 26. 14:06

 

 

코틀린은 자바와 다르게 클래스명을 파일명과 똑같이 지을 필요가 없다.

그리고 클래스를 한 파일 안에 여러 개 생성할 수도 있다.

 

class Human {
  val name = "chacha"
  
  fun eatingCake() {
    println("This is so YUMMY~~")
  }
}

fun main() {
  val human = Human()
  human.eatintCake()
  
  println("This human's name is ${human.name}")
}

// 출력 
This is so YUMMY~~
This human's name is chacha

 

자바에서는 new 키워드를 작성해서 클래스 객체를 생성했었는데

Human human = new Human();

 

코틀린은 그냥 써주면 된다.

val human = Human()

 

 

 

근데 변수 선언이 아니라 객체 생성할 때 값을 할당하고 싶으면

생성자를 이용하면 된다.

 

 

java

// java
class Human {
    private String name;

    // 기본 생성자
    public Human() {
        this.name = "defaultName";
    }

    // 생성자 오버로딩
    public Human(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
    
}

public static void main(String[] args) {
    Human human = new Human("jaehyun");
    System.out.println("This human's name is " + human.getName());
}

 

물론 어노테이션 쓰면 간단하긴 한데 어쨌든 ..

 

 

Kotlin

// kotlin
class Human(val name: String = "defaultName") {

    fun eatingCake() {
        println("Yummy")
    }
}

fun main() {
    val human = Human("jaehyun")
    val stranger = Human()
    
    println("This human's name is ${human.name}")
}

 

Human 안에 name 프로퍼티를 선언해야한다.

(프로퍼티 = 클래스 안에 속한 변수)

 

Human(val name: String)

기본값을 줘야 기본 생성자도 같이 만들어준다.

기본값은 선택.

 

 

 

근데 이러면 코틀린은 생성자에서  자바처럼 코드블록을 쓸 수가 없기 때문에

코드블록 넣고 싶으면~~~

init 쓰면 된다.

 

// kotlin
class Human(val name: String = "defaultName") {

    init {
      println("New Human has been horn!!")
    }
    
    fun eatingCake() {
        println("Yummy")
    }
}

fun main() {
    val human = Human("jaehyun")
    val stranger = Human()
    
    println("This human's name is ${human.name}")
}

 

// 주생성자.

init 도 주 생성자이기 때문에 같이 실행된다.

 

이러면 Human("jaehyun") 으로 한 번, Human() 으로 한 번,  총 두 번 생성했으므로 

출력이

New Human has been born!! 이 두 번 출력된다.

 

 

 

 

 

 

// 부생성자

 

 

Java

public class Human {

    private String name;
    private int age;

    // 기본 생성자
    public Human() {
    }

    // 전체 필드 생성자
    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getter
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

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

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

 

 

kotlin

constructor 라는 부생성자를 이용하면 된다.

class Human(val name: String = "HAHA") {
    constructor(name: String, age: Int) : this(name) {
        // 주생성자에게 위임해야 한다.
        println("my name is ${name}, ${age}years old")
    }
    
    init{
    println("New~")
    }
    
    fun eatingCake() {
      println("so YUMMY~~")
    }
}

fun main() {
  val human = Human()
  human.eatingCake()
  
  val mom = Human("cha", 25)
}

// 출력

 

순서가

주생성자 호출 -> eatingCake실행 -> 주생성자 호출로 init 실행  -> 부생성자 호출

 
New~
so YUMMY~~
New~
my name is cha, 25years old

 

 

** constructor 가 아무리 많아도 init 먼저 실행

 

 


 

 

 

 

만약 어노테이션 쓴다면 자바도 간단해지긴 한다.

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Human {

    private String name;
}

 

// 롬복이 자동으로 생성해주는 것
public Human() { }

public Human(String name) {
    this.name = name;
}

 

 

 


 

 

다형성

 

코틀린의 다형성도 자바의 다형성과 같다. 문법만 조금 다르다.

 

상속받을 때는

interface 또는 open class 를 사용한다.

 

1. interface 사용

// 인터페이스 생성
interface A {
    fun aa()
}

class B : A {
    override fun aa() {
        println("B다")
    }
}

class C : A {
    override fun aa() {
        println("C다")
    }
}


// 메인에서 사용
fun main() {
    val b: A = B()
    b.aa()   // "B다"

    val bb: B = B()
    bb.aa()  // "B다"

    val c: A = C()
    c.aa()   // "C다"
}

 

 

 

 

2. open class 사용

open class A {
    open fun aa() {
        println("A다")
    }
}

class B : A() {
    override fun aa() {
        println("B다")
    }
}


// 메인에서 사용
fun main() {
    val a = A()
    a.aa()   // A다

    val b = B()
    b.aa()   // B다
}

 

 

 

 

 

 

class를 상속받을 때, 상속받을 클래스 앞에 open 을 써주어야 하고 (같은 파일 내에 있더라도 꼭 써야함)

함수를 override할 때 해당 함수 앞에 open 을 써주어야 한다.

기본이 final 이기 때문.

open class Human() {

  open fun sing() {
    println("lalala")
  }
}

class Korean :Human(){

  override fun sing(){
    println("랄랄라")
  }
}

 

fun main() {
  val korean = Korean()
  korean.sing()
  super.sing()
}

// 출력
랄랄라
lalala

 

super 사용해서 부모 메서드도 쓸 수 있다.

 

 

 

 


 

 

주생성자 만들어서 기본값을 HAHA로 주었기 때문에 

(val name: String = "HAHA") 

기본생성자도 사용할 수 있다.

 

val name 은 생성자 파라미터인 동시에 프로퍼티.

(자식의 name 은 부모의 프로퍼티.

프로퍼티 = 클래스 에 속한 변수.

class Human(name: String) {
    val name = name
}

결국 이렇게 내부적으로 동작하기 때문에. )

 

즉 val name 은 Human 클래스의 멤버변수.

 

그래서 자식 클래스는 상속을 통해 sing 메서드에서 name 파라미터를 쓸 수 있다.

open class Human(val name: String = "HAHA") {
    
    open fun sing(){
      println("lalala")
    }
}

class Korean :Human() {
  
  override fun sing(){
    super.sing()
    println("랄랄라")
    println("my name is ${name}")
  }
}

// 출력
lalala
랄랄라
my name is HAHA

 

 

자바는 어노테이션 써도 그냥 생성자와 getter/setter 만 자동 생성되는 것이고

(@NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor, @Data 쓰는 경우)

 

변수는 직접 선언을 해야한다.

private String name;
private int age;

 

 

 

 

근데 코틀린은

class Human(val name: String, var age: Int)

 

이 한 줄이 동시에

  • 필드 생성
  • 생성자 생성
  • getter 생성
  • setter 생성 (var일 경우)

를 모두 정의한다.