coding study/Android

[Kotlin] 추상 클래스 , 인터페이스

computer engineering.초코나무쑵 2022. 1. 28. 15:56

[앞으로 만들 클래스]

  • Dwelling: 모든 주택에 공통으로 적용되는 정보를 담고 있는 구체적이지 않은 집을 나타내는 기본 클래스
  • SquareCabin: 바닥 면적이 정사각형인 나무로 만든 정사각형 통나무집
  • RoundHut: 바닥 면적이 원형인 짚으로 만든 둥근 오두막이고 RoundTower의 상위 요소
  • RoundTower: 바닥 면적이 원형이고 층이 여러 개인 돌로 만든 둥근 타워

 

[추상 클래스]

'추상' 클래스는 완전히 구현되지 않아서 인스턴스화할 수 없는 클래스이다. 큰 틀을 짜둔다! 라는 의미를 갖고있다고 생각하면 편하다. 추상클래스를 사용하여 클래스를 생성하고 실제 객체 인스턴스를 빌드한다.

abstract class Dwelling(){
}

이처럼 Dwelling( ) 추상 클래스를 만든 후 공통적인 요소들을 Dwelling( )에 넣을 것인데 우선 (1). 건축재료 (2). 거주자 수 이다. 

val buildingMaterial: String

이때 건축재료나 거주자 수를 위 이미지처럼 val로 그냥 선언하면 안된다. 

abstract val buildingMaterial: String
abstract val capacity: Int

abstract 키워드를 접두사로 붙여준다. 이는 여기서 정의되지 않았음을 알리는 것이고 이유는 각 클래스 즉 건물마다 건축재료 종류 및 거주자 수는 각각 다르기 때문에 변할 수 있는 부분이다.  

특정 유형의 주택에 관한 서브클래스에서 정의해야 하는 부분이다.

abstract class Dwelling(private var residents: Int) {

   abstract val buildingMaterial: String
   abstract val capacity: Int

   fun hasRoom(): Boolean {
       return residents < capacity
   }
}

-> residents를 Dwelling 클래스의 생성자에 전달되는 매개변수로 만들 수도 있다.

이때  residents 속성은 인스턴스가 만들어진 후 거주자 수가 변경될 수 있기에 var로 표현한다. 

 

* hasRom( ) 함수주택의 capacity와 현재 residents 수가 모두 정의된 상태에서 주택의 또 다른 거주자를 위한 공간이 있는지 확인하기 위해 만든 것이다.

 

[ 서브클래스 만들기 ]

SquereCabin , RoundHut, RoundTower 서브클래스 만들기

 

1) SquareCabin 클래스 이름 다음에 콜론 " : " 을 추가하고 상위 클래스를 초기화하는 호출을 추가하면 상속 관계를 나타낸다.

ex) Dwelling 클래스가 SquereCabin의 상위클래스라고 한다면 class SquareCabin : Dwelling( ) 으로 나타낼 수 있다.

 

2) 슈퍼클래스에서 확장할 때는 예상하는 필수 매개변수를 전달해야 한다.

  Dwelling에는 입력으로 거주자 명수가 필요하다. 따라서 아래 예시와 같이 고정된 거주자 수를 전달할 수 있다.

ex) calss SquareCabin : Dwelling(3)

 

3) 하지만 유연성을 높여 가변적으로 구현할 수도 있는데 이때는 residents(거주자)를 SquareCabin 클래스 정의의 매개변수로 만든다. ( 이때, residents를 val로 선언하지 않는 이유는 이미 상위 클래스 Dwelling에서 선언된 속성을 재사용하고 있으므로.)

--> ex) calss SquareCabin(residents : Int) : Dwelling(residents)

 

class SquareCabin(residents: Int) : Dwelling(residents) {
    override val buildingMaterial = "Wood"
    override val capacity = 6
}
class RoundHut(residents: Int) : Dwelling(residents) {
    override val buildingMaterial = "Straw"
    override val capacity = 4
}

[1차적 완성 코드]

fun main() {
    val squareCabin = SquareCabin(6)

    with(squareCabin) {
        println("\nSquare Cabin\n============")
        println("Capacity: ${capacity}")
        println("Material: ${buildingMaterial}")
        println("Has room? ${hasRoom()}")
    }
}

abstract class Dwelling(private var residents: Int) {
    abstract val buildingMaterial: String
    abstract val capacity: Int

    fun hasRoom(): Boolean {
       return residents < capacity
   }
}

class SquareCabin(residents: Int) : Dwelling(residents) {
    override val buildingMaterial = "Wood"
    override val capacity = 6
}

 

[ with를 이용해 코드를 단순화 할 수 있다. ] 

만약 with를 사용하지 않는다면 아래처럼 인스턴스 이름을 계속 붙여서  출력해야한다.

 println("Capacity: ${squareCabin.capacity}")
 println("Material: ${squareCabin.buildingMaterial}")
 println("Has room? ${squareCabin.hasRoom()}")

클래스의 특정 인스턴스로 작업하고 이 인스턴스의 여러 속성과 함수에 액세스해야 한다면 with 문을 사용하여 '이 인스턴스 객체로 다음 작업을 모두 실행'하라고 나타낼 수 있다.

 

with 키워드로 시작하고 괄호로 묶인 인스턴스 이름, 실행하려는 작업이 포함된 중괄호가 차례로 이어진다.