Data Class
데이터클래스 예시
package ch01
data class User(val id: Long, var name: String) // 매개변수는 하나 이상 반드시 입력해야함.
//데이터 클래스는 추상, 오픈, 봉인, 내부 클래스일 수 없다.
fun main() {
val user1 = User(1, "Sunghyeon") // 데이터 클래스 객체 생성
// val name = user1.name // Sunghyeon을 지목
// println(name)
user1.name = "Michael" // user1은 더이상 Sunghyeon이 아니다.
val user2 = User(1, "Michael")
println(user1.equals(user2)) //any 타입이기에 equlas를 사용가능. 결과값: true
println("User Details: $user1")
val updatedUser = user1.copy(name = "Denis panjuta") //user1은 여전히 Michael이지만 updateuser은 denis panjuta가 된다.
println(user1)
println(updatedUser) // "denis panjuta"가 출력됨
println(updatedUser.component1()) // print 1
println(updatedUser.component2()) // print denis panjuta
val (id, name) = updatedUser
println("id=$id, name=$name")
}
- val, var로 매개변수 하나 이상 반드시 입력해야 한다.
- 데이터클래스는 상속 받을 수 없다.
- abstract, open, sealed, ineer를 붙일 수 없다.
(너무 짧게 공부해서 책보고 다시 공부할 것)
클래스 챌린지
저희 예제의 MobilePhone 클래스를 __를 이용해 확장해 주세요
class MobilePhone(osName: String, brand: String, model: String){
init {
println("The phone $model from $brand uses $osName as its Operating System")
}
}
- 조건
배터리 잔량을 나타내는 멤버를 추가합니다
(“battery”라고 지정합시다
0과 50 사이의 숫자로 초기화합니다)
그런 다음 “chargeBattery” 함수를 추가합니다
얼마가 충전되었는지에 대한 세부사항이 필요합니다
이제 휴대폰 배터리가 얼마였는지, 얼마나 충전되었는지, 이제 배터리가 얼마인지 값이 출력될 것입니다
클래스의 개체를 만들고 이 함수를 호출합시다
배터리를 30만큼 충전해보세요
- 풀이
fun main() {
val mobilePhone = MobilePhone("IOS", "Apple", "iphone12Pro")
val charge = mobilePhone.chargeBattery(20)
}
class MobilePhone(osName: String, brand: String, model: String) {
private var battery = 30
init {
println("The phone $model from $brand uses $osName as its Operating System")
}
fun chargeBattery(chargeBy: Int) {
println("충전 전 배터리잔량은 $battery 이고, 충전 후 배터리 잔량은 ${battery + chargeBy} 입니다.")
battery += chargeBy
}
}
상속
// Super class (부모 클래스)
open class Car1(val name: String, val brand: String) {
open var range: Double = 0.0
fun extendRange(amount: Double) {
if (amount > 0)
range += amount
}
open fun drive(distance: Double) {
println("drove for $distance Km")
}
}
// 서브클래스 of Car Class
class ElectricCar(name: String, brand: String, batteryLife: Double) : Car1(name, brand) {
override var range = batteryLife * 6
override fun drive(distance: Double) {
println("전기로 $distance km만큼 더 운전했다")
}
fun drive() {
println("전기로 $range km만큼 더 운전했따")
}
}
fun main() {
var audiA3 = Car1("A3", "Audi")
var teslaS = ElectricCar("S-Model", "Tesla", 85.0)
teslaS.extendRange(200.0)
teslaS.drive()
audiA3.drive(200.0)
teslaS.drive(200.0)
}
- 부모 클래스 == Super Class
- 자식 클래스 == Sub Class
- open class : 다른 클래스에서 상속 받을 수 있다.
- open method : 해당 메서드를 하위클래스에서 override할 수 있다.
인터페이스
// 인터페이스는 클래스 기능을 확장하게 해준다.
// 예를 들어 자동차 클래스가 어떤 특성을 가진 인터페이스 기능을 확장해줄 수 있다.
// 인터페이스는 모든 프로퍼티와 함수를 구현해줄 수 있지만 꼭 그럴 필요는 없다.
// 만약 구현된 부분이 있다면 그 인터페이스를 사용하는 클래스가 오버라이딩을 할 수 있다.
interface Drivable {
val maxSpeed: Double
fun drive(): String // 구현된 함수가 없기에 함수 헤드만 있다.
fun brake() { //
println("The drivable is braking")
}
}
// Car1 Class가 Drivable 인터페이스의 기능을 확장한다면, 인터페이스의 프로퍼티를 입력해야한다.
// override val maxSpeed, drive를 입력해야겠지? drive부분은 27번을 확인할 것
open class Car1(override val maxSpeed: Double, val name: String, val brand: String) : Drivable {
open var range: Double = 0.0
fun extendRange(amount: Double) {
if (amount > 0)
range += amount
}
// 30번에 이미 fun drive가 있다. Double 타입이라 함수 구조가 같지 않아서 적용이 안된 것이다.
// override fun drive(): String = "driving the interface drive"
override fun drive(): String { // 이 drvie는 인터페이스에서 온 함수기 때문에 다른 drive로 보면 된다.
return "driving the interface drive"
}
open fun drive(distance: Double) {
println("drove for $distance Km")
}
}
// 서브클래스 of Car Class
class ElectricCar(maxSpeed: Double, name: String, brand: String, batteryLife: Double) : Car1(maxSpeed, name, brand) {
override var range = batteryLife * 6
override fun drive(distance: Double) {
println("전기로 $distance km만큼 더 운전했다")
}
override fun drive(): String {
return "전기로 $range km만큼 더 운전했따"
}
override fun brake() {
super.brake()
println("brake inside of electric car")
}
}
fun main() {
var audiA3 = Car1(200.0, "A3", "Audi")
var teslaS = ElectricCar(240.0, "S-Model", "Tesla", 85.0)
teslaS.extendRange(200.0)
teslaS.drive()
teslaS.brake()
audiA3.brake()
audiA3.drive(200.0)
teslaS.drive(200.0)
}
코드 해설
Car1 클래스가 drivable 인터페이스를 확장하기 때문에, drivable의 변수, 프로퍼티, 함수를 구현해야 한다.
(maxSpeed, drive).
프로퍼티는 주 생성자에서 구현했고 함수는 그 아래 override해서 구현했다.
brake는 이미 구현을 해놨지만, 만약 해야한다면 서브 클래스에서 override할 수 있다.
이 때, super.brake 코드가 발생하는데, 이는 super클래스인 Car1에 brake 기능이 구현되지 않았으니
인터페이스에서 받아오게 된다.왜 인터페이스를 사용하는가?
나중에 구현하고 싶은 특정 함수와 클래스 프로퍼티가 있다면
유용하다 바로 구현하고 싶지 않을때 준비하는개념
또 구체적인 함수보디를 아직 만들고 싶지 않을때.
추상클래스
abstract class Mammal( // 추상 명사
private val name: String,
private val origin: String,
private val weight: Double
) { // 3가지는 구체적인 프로퍼티
// 추상적인 프로퍼티의 형태
abstract var maxSpeed: Double // 추상적인 프로퍼티. Sub Class가 오버라이딩 해야함.
// 추상적인 메서드 형태
abstract fun run() // body가 없는 메서드
abstract fun breath()
// 구체적인 메서드
fun displayDetails() {
println("Name: $name, Origin: $origin, Weight: $weight, Max Speed: $maxSpeed")
}
}
class Human(
name: String, origin: String, weight: Double,
override var maxSpeed: Double
) : Mammal(name, origin, weight) {
override fun run() {
println("Runs on two legs")
}
override fun breath() {
println("Breath through mouth or nose")
}
}
class Elephant(
name: String, origin: String, weight: Double,
override var maxSpeed: Double
) : Mammal(name, origin, weight) {
override fun run() {
println("Runs on four legs")
}
override fun breath() {
println("Breath through mouth or nose")
}
}
fun main() {
val human = Human("Sunghyeon", "Korea", 59.5, 20.0)
val elephant = Elephant("Doto", "Afreeca", 6000.0, 40.5)
// val mammal = Mammal("Sunghyeon", "Korea", 59.5, 15.5) 불가능함. 상속받은 클래스에선 가능
human.run()
elephant.run()
human.breath()
elephant.breath()
}
- 추상클래스와 인터페이스의 차이는 무엇인가?
참고링크) https://interlude.tistory.com/15
(아직 확 와닿는 정보는 아니다..)
여기까지가 객체지향 기초파트 종료
다음은 기초 더배우기 파트(?)로 넘어간다.
공부의 부족인지 개념도 헷갈리고 머리에 딱 꽂히지 않는다.
스스로 코딩해보라고 하면 못할거같다. 연습만이 답인듯하다
'Kotlin' 카테고리의 다른 글
리스트 (0) | 2023.12.22 |
---|---|
배열 (1) | 2023.12.22 |
내일배움캠프 12.18 TIL (1) | 2023.12.22 |
내일배움캠프 12.15 TIL (2) | 2023.12.22 |
객체지향 프로그램 기초개념 5가지 (1) | 2023.12.22 |