▶️ 일반 자료형간의 변환 예시
fun main() {
var num1 = 20
var num2 = 30.2
var num3 = num2.toInt()
var num4 = num1.toDouble()
var strNum5 = "10"
var strNum6 = "10.21"
var num5 = Integer.parseInt(strNum5) // 숫자 형태의 문자열은 싱글턴으로 선언된 Integer라는 클래스에 parseInt()라는 메소드를 부르고, 그 파라미터에 문자열 형태의 숫자인 변수를 넣어주면 숫자로 바꿔서 리턴해준다.
var num6 = strNum6.toDouble() // 실수 형태의 문자열은 변수에 바로 .toDouble()을 하면 double로 바꿔서 리턴해주는 메소드를 사용.
println("num3: $num3")
println("num4: $num4")
println("num5: $num5")
println("num6: $num6")
}
/* 결과
num3: 30
num4: 20.0
num5: 10
num6: 10.21
*/
▶️ 객체 자료형간의 변환 예시
fun main() {
println("몇 마리를 생성하시겠습니까?")
var count = readLine()!!.toInt()
var birds = mutableListOf<Bird>() // birds에는 Bird 클래스만 들어갈 수 있다고 제한을 둠.
for(idx in 0..count-1) { // 예를 들어, count에 2를 입력했다면 2-1해서 0,1 즉 2마리를 생성할 수 있는 for문
println("조류의 이름을 입력해주세요")
var name = readLine()!!
// as Bird는 생략가능(as Bird는 업캐스팅으로 만들겠다는 것. 그런데 위에서 변수 birds에는 Bird 클래스만 들어갈 수 있다고 제한을 뒀기 때문에 Sparrow를 바로 넣을 수 없는데, Bird클래스로써 들어갈 수 있다고 업캐스팅하는 것.)
birds.add(Sparrow(name) as Bird) // Sparrow 클래스의 객체를 만듦. Sparrow로 만들었지만, 상속관계에 있는 Bird로써 birds 리스트에 들어갈 수 있다.
}
println("============조류 생성완료============")
for(bird in birds) {
bird.fly() // 참새나 비둘기 객체를 따로따로 만들어서 fly()하는 것이 아니라, Bird 안에 리스트를 만들고, 업캐스팅을 통해 객체를 만들어서 sparrow.fly()나 pigeon.fly() 말고 bird.fly()하면 된다.
}
}
open class Bird(name: String) {
var name: String
init {
this.name = name
}
fun fly() {
println("${name}이름의 조류가 날아요~")
}
}
class Sparrow(name: String): Bird(name) { // 생성자에 위에서 입력한 name를 넘기고, 또 상속 받은 Bird 클래스의 name에 넘김.
}
/* 결과
몇 마리를 생성하시겠습니까?
2
조류의 이름을 입력해주세요
참새
조류의 이름을 입력해주세요
비둘기
============조류 생성완료============
참새이름의 조류가 날아요~
비둘기이름의 조류가 날아요~
*/
fun main() {
println("몇 마리를 생성하시겠습니까?")
var count = readLine()!!.toInt()
var birds = mutableListOf<Bird>()
for(idx in 0..count-1) {
println("조류의 이름을 입력해주세요")
var name = readLine()!!
birds.add(Sparrow(name) as Bird)
}
println("============조류 생성완료============")
for(bird in birds) {
bird.fly()
}
// 다운캐스팅 오류
// var s1:Sparrow = birds.get(0)
// 윗줄의 주석을 풀면 오류가 난다. birds.get(0)을 Sparrow에 넣는 것은 불가능하기 때문이다. birds는 Sparrow보다 크고, 더 많은 정보를 가진 Bird 타입이고, Sparrow는 Bird가 가진 정보를 모두 가지고 있지 않기 때문에 Sparrow로의 다운캐스팅은 안된다. 하지만 자식인 Sparrow는 부모 Bird로는 갈 수 있다.
}
open class Bird(name: String) {
var name: String
init {
this.name = name
}
fun fly() {
## println("${name}이름의 조류가 날아요~")
}
}
class Sparrow(name: String): Bird(name) {
}
fun main() {
var name = "aa" // 안에 있는 값을 보는 게 아니라 변수가 어떤 자료형인지를 보는 것.
if(name is String) {
println("name은 String 타입입니다")
} else {
println("name은 String 타입이 아닙니다")
}
}
▶️ Pair를 활용해서 두 개의 인스턴스 리턴
fun main() {
var chicken = Chicken() // Chicken 클래스 만들고 인스턴스
var eggs = chicken.getEggs()
var listEggs = eggs.toList() // 리스트화([]형태로 출력됨)
//first, second로 관리하는 경우
//var firstEgg = eggs.first
//var secondEgg = eggs.second
// 리스트로 관리하는 경우
var firstEgg = listEggs[0] // 달걀
var secondEgg = listEggs[1] // 맥반석
println("달걀의 종류는 ${eggs} 입니다.")
println("리스트 달걀의 종류는 ${listEggs} 입니다.")
println("첫번째 달걀의 종류는 ${firstEgg} 입니다.")
println("두번째 달걀의 종류는 ${secondEgg} 입니다.")
}
class Chicken {
fun getEggs(): Pair<String, String> { // 리턴 타입이 Pair이고, 첫 번째, 두 번째 파라미터가 String 타입.
var eggs = Pair("달걀", "맥반석") // Pair라는 객체는 달걀, 맥반석이라는 두 개의 값을 가지고, 그걸 eggs 변수에 넣음.
return eggs
}
}
/* 결과
달걀의 종류는 (달걀, 맥반석) 입니다.
리스트 달걀의 종류는 [달걀, 맥반석] 입니다.
첫번째 달걀의 종류는 달걀 입니다.
두번째 달걀의 종류는 맥반석 입니다.
*/
▶️ Triple를 활용해서 세 개의 인스턴스 리턴
fun main() {
var chicken = Chicken()
var eggs = chicken.getThreeEggs()
var listEggs = eggs.toList()
//first, second, third로 관리하는 경우
//var firstEgg = eggs.first
//var secondEgg = eggs.second
//var eggTime = eggs.third
// 리스트로 관리하는 경우
var firstEgg = listEggs[0]
var secondEgg = listEggs[1]
var eggTime = listEggs[2]
println("달걀의 정보는 ${eggs} 입니다.")
println("리스트 달걀의 정보는 ${listEggs} 입니다.")
println("첫번째 달걀의 종류는 ${firstEgg} 입니다.")
println("두번째 달걀의 종류는 ${secondEgg} 입니다.")
println("달걀은 ${eggTime}에 나왔습니다.")
}
class Chicken {
fun getTwoEggs(): Pair<String, String> {
var eggs = Pair("달걀", "맥반석")
return eggs
}
fun getThreeEggs(): Triple<String, String, Int> {
var eggs = Triple("달걀", "맥반석", 20230101)
return eggs
}
}
/* 결과
달걀의 정보는 (달걀, 맥반석, 20230101) 입니다.
리스트 달걀의 정보는 [달걀, 맥반석, 20230101] 입니다.
첫번째 달걀의 종류는 달걀 입니다.
두번째 달걀의 종류는 맥반석 입니다.
달걀은 20230101에 나왔습니다.
*/
▶️ let function의 활용
fun main() {
var strNum = "10"
// let {}은 현재 내 객체를 it으로 넘겨서 {} 안에서 처리하고 리턴해서 result에 대입해 준다.
var result = strNum?.let { // strNum("10")이 null인지 검사하고, let{}을 이용할 때 {} 안에서는 it으로 strNum을 대체해서 쓸 수 있다.
// 중괄호 안에서는 it으로 활용함
Integer.parseInt(it) // it은 strNum을 대체해서 쓰였고, it을 넘겼을 때 문자열 형태의 숫자를 숫자로 바꿔서 result에 저장.
}
println(result!!+1) // result가 null이 아님을 보장하고 1을 더했을 때의 값을 출력
}
// 결과 --> 11
▶️ with function의 활용
fun main() {
var alphabets = "abcd" // 값이 들어있으니 null이 아닌 게 확실!
with(alphabets) {
// var result = this.subSequence(0, 2)
var result = subSequence(0, 2) // this 생략해도 alphabets.subSequence를 부르는구나 알 수 있음.
println(result)
}
}
// 결과 --> ab
▶️ also function의 활용
fun main() {
var student = Student("참새", 10)
var result = student?.also { // 객체 student가 null이 아닐 때만 실행하게 하고 also 실행
it.age = 50 // {} 안에 student를 it으로 넘김 -> resultdp 50 들이(age가 바뀐 새로운 student 객체가 result에 대입 됨
}
result?.displayInfo()
student.displayInfo()
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
/* 결과
이름은 참새 입니다
나이는 50 입니다
이름은 참새 입니다
나이는 50 입니다
*/
▶️ apply function의 활용
fun main() {
var student = Student("참새", 10)
var result = student?.apply { // student가 null이 아닐 때 실행해서 apply 실행
student.age = 50 // this로 들어옴.(왜 this 말고 student 그대로 썼지?) 객체 상태를 변환하고 바로 반환해 줌.
}
result?.displayInfo()
student.displayInfo()
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
/* 결과
이름은 참새 입니다
나이는 50 입니다
이름은 참새 입니다
나이는 50 입니다
*/
▶️ run function의 활용
fun main() {
var totalPrice = run { // 임시로 영역을 만든 것
var computer = 10000
var mouse = 5000
computer + mouse
}
println("총 가격은 ${totalPrice}입니다")
}
// 결과 --> 총 가격은 15000입니다
fun main() {
var student = Student("참새", 10)
student?.run { // null이 아닐 때만 run을 하라고 할 수 있다.(with 쓰면 with 아래에 student 넣고 써야 함)
displayInfo() // this 생략하고 메소드 호출. student.displayInfo()라는 뜻
}
}
class Student(name: String, age: Int) {
var name: String
var age: Int
init {
this.name = name
this.age = age
}
fun displayInfo() {
println("이름은 ${name} 입니다")
println("나이는 ${age} 입니다")
}
}
/* 결과
이름은 참새 입니다
나이는 10 입니다
*/
// 수신객체 자체를 람다의 수신객체로 전달하는 방법
public inline fun <T, R> T.run(block: T.() -> R): R
public inline fun <T> T.apply(block: T.() -> Unit): T
public inline fun <T, R> with(receiver: T, block: T.() -> R): R
// 수신객체를 람다의 파라미터로 전달
public inline fun <T> T.also(block: (T) -> Unit): T
public inline fun <T, R> T.let(block: (T) -> R): R
// Scope Function을 중첩으로 사용할 경우 누가 누구의 범위인지 알수 없다!
// Implicit parameter 'it' of enclosing lambda is shadowed 경고 발생!
data class Person(
var name: String = "",
var age: Int? = null,
var child: Person? = null
)
// 잘못된 예시
Person().also {
it.name = "한석봉"
it.age = 40
val child = Person().also {
it.name = "홍길동" // 누구의 it인지 모른다!
it.age = 10 // 누구의 it인지 모른다!
}
it.child = child
}
// 수정한 예시
Person().also {
it.name = "한석봉" // 외부에 있는 it
it.age = 40
val child = Person().also { c ->
c.name = "홍길동" // 내부에 있는 c
c.age = 10
}
it.child = child
}
Scope에서 접근방식 this | Scope에서 접근방식 it | |
---|---|---|
블록 수행 결과를 반환 | run(권장), with | let |
객체 자신을 반환 | apply | also |