nueijeel

[Kotlin 이론] 0516 Any, 추상 클래스와 인터페이스 본문

Kotlin

[Kotlin 이론] 0516 Any, 추상 클래스와 인터페이스

nueijeel 2023. 5. 24. 23:12

2023.05.16

 

 

1. Any

 

Any

: 코틀린에서 모든 클래스가 직접 혹은 간접적으로 상속받는 클래스

 

자바의 최상위 클래스가 java.lang.Object 클래스라면 코틀린의 최상위 클래스는 Any 클래스이다. 

클래스 정의 시 상속에 대한 코드를 별도로 작성하지 않는다면 Any 클래스를 자동으로 상속받는다.

 

fun main(){
    val a1 : Any = TestClass1()
    println(a1)
}
class TestClass1

 

body 구현이나 상속 등을 사용하지 않는 TestClass1을 선언만 했다. 해당 클래스는 Any 클래스를 자동으로 상속받기 때문에, 객체를 Any형 참조 변수에 담아 사용할 수 있다.

 

Any 클래스 안에는 클래스가 갖춰야 할 기본적인 기능들이 들어있다.

Any 클래스가 오버라이딩을 제공하는 메서드들을 살펴보자.

 

fun main(){
    val t1 = TestClass(100, 200)
    println(t1)
    
    val t2 = TestClass(1000, 2000)
    val t3 = TestClass(100, 200)
    
    if(t1==t2) println("t1과 t2는 같습니다")
    else println("t1과 t2는 다릅니다")
    
    if(t2==t3) println("t2와 t3은 같습니다")
    else println("t2와 t3은 다릅니다")
}
class TestClass(var a1:Int, var a2:Int){
    //toString 메서드 오버라이딩
    override fun toString(): String{
    	println("a1: $a1")
        println("a2: $a2")
    }
    
    //equals 메서드 오버라이딩
    overrride fun equals(other:Any?):Boolean{
    	if(other != null){
        	val temp = other as TestClass
            if(this.a1 == temp.a1 && this.a2 == temp.a2){
            	return true
            } else{
            	return false
            }
        }
    }
}

 

toString() 메서드는 객체의 정보를 문자열로 반환하기 위해 사용하는 메서드이다. 코틀린에서 제공하는 출력문을 사용해 변수의 값을 출력하면 내부에서 toString() 메서드가 호출되어 값을 문자열로 반환해줘서 출력하는 것이다.

 

equals() 메서드는 비교 연산자인 ==를 사용하면 자동으로 호출되는 메서드이다. == 연산자를 기준으로 좌측에 있는 변수를 통해 equals() 메서드가 호출되고, == 연산자의 우측에 있는 요소가 equls() 메서드의 매개변수로 들어온다. 이 메서드가 반환하는 boolean 값이 == 연산의 결과로 쓰인다.

 

 

 

2. 추상 클래스

 

추상 클래스

: 추상 메서드를 가지고 있는 미완성된 클래스

 

추상 메서드

: 기능이 구현되지 않은 미완성된 메서드

 

추상 클래스는 완성된 클래스가 아니기 때문에 객체를 생성할 수 없다. 따라서 추상 클래스를 상속받은 클래스에서 추상 클래스의 추상 메서드를 오버라이딩해 사용한다. 

메서드의 오버라이딩에 강제성을 주기 위해 추상 메서드를 사용한다.

 

open  abstract  class  클래스명 {
        open  abstract  fun  메서드명 ( )
}

abstract 키워드는 추상 요소를 나타낸다. 그런데 그 상태에서 클래스의 상속과 메서드의 오버라이딩이 가능하게 해야하기 때문에 open 키워드도 붙여줘야 한다.

 

fun main(){
    val sub = SubClass()
    sub.testMethod()
}
open abstract class TestClass(){
    open abstract fun testMethod()
}
class SubClass : TestClass(){
    override fun testMethod(){
    	println("추상 메서드 오버라이딩")
    }	
}

 

위와 같이 추상 메서드 testMethod()를 가진 추상 클래스 TestClass를 생성하고, 이를 상속받아 오버라이딩하는 자식 클래스 SubClass를 생성했다. SubClass의 객체를 생성해 오버라이딩한 메서드에 접근할 수 있다.

 

 

 

3. 인터페이스

 

인터페이스

: 코틀린에서 객체를 다양한 타입의 변수에 담기 위해 활용하는 개념

 

코틀린은 다중 상속을 지원하지 않지만, 하나의 클래스가 여러 개의 인터페이스를 구현할 수 있다. 

추상 클래스와 비슷한 목적으로 인터페이스를 사용하는데, 자식 클래스에서 하나의 클래스만 상속 가능하기 때문에 인터페이스를 사용하면 여러 기능을 구현할 수 있다는 장점이 있다.

 

인터페이스는 추상 메서드와 일반 메서드 모두를 구현해 사용할 수 있는데, 추상 메서드에는 별다른 키워드를 작성하지 않고 body 구현을 하지 않으면 된다.

 

fun main(){
    val tc1 : Inter1 = TestClass1()
    val tc2 : TestClass1 = TestClass1()
    
    tc1.method1()
    tc1.method2()
    
    tc2.method1()
    tc2.method2()
}
interface Inter1 {
    fun method1()
    fun method2(){
        println("Inter1의 method2")
    }
}
class TestClass1 : Inter1{
    override fun method1() {
        println("TestClass1의 method1입니다")
    }
}

 

Inter1의 method1은 body가 기술되지 않은 추상 메서드이고, method2는 body가 구현된 일반 메서드이다.

 

인터페이스 Inter1을 구현한 클래스 TestClass1에서 추상 메서드 method1()을 오버라이딩했다.

 

메인 함수에서 Inter1형 참조 변수와 TestClass1형 참조 변수에 각각 클래스 객체를 생성해 담았다. 두 객체 참조 변수를 이용해 Inter1의 일반 메서드 method2와 TestClass1의 오버라이딩 메서드 method1()을 잘 호출하는 것을 확인할 수 있다.

 

interface Inter1 {
    fun method1()
}
interface Inter2{
    fun method2()
}
class TestClass : Inter1, Inter2{
    override fun method1() {
        println("TestClass의 method1입니다")
    }
    override fun method2() {
        println("TestClass의 method2입니다")
    }
}

 

위와 같이 TestClass 하나에 여러 개의 인터페이스를 구현할 수 있다.

728x90