✏️ Lambda
1. Lambda식
- Lambda식은 이름이 없어도 함수 역할을 하는 익명 함수의 하나의 형태로, 화살표 표기법을 사용한다.
- Lambda식은 함수에서 파라미터나 리턴값이 될 수 있다.
- Lambda식의 기본 정의
- 타입 추론이 가능하도록
- lambdaName 뒤에 inputType과 outputType을 작성하거나
- 이를 생략하고 argumentList 뒤에 inputType을 작성할 수 있다.
- input은 여러개일 수 있으므로 inputType에는 항상 괄호를 써야하지만, output은 항상 하나이므로 괄호를 생략해도 된다.
val lambdaName: (inputType) -> (outputType) = {argumentList -> codeBody}
val lambdaName = {argumentList: InputType -> codeBody}
val square: (Int) -> (Int) = {number -> number * number}
print(square(12))
val nameAge = {name: String, age: Int ->
"My name is ${name}. I'm ${age}.
}
print(nameAge("minha", 25))
2. 확장 함수
val introduce: String.(Int) -> String = {
"My name is ${this}. I'm ${it}."
}
val name = "minha"
println(name.introduce(25))
My name is minha. I'm 25.
3. SAM 변환
- 안드로이드 프로그래밍을 하다 보면 setOnClickListener 등의 함수를 두 가지 방법으로 사용할 수 있는 것을 알 수 있다.
- 위는 객체 표현식(object expression), 아래는 람다식을 사용한 것이다.
- 이러한 경우 람다식을 사용하기 위해서는 익명 내부 함수가 "Java로 작성된 딱 하나의 메소드만 가지는 인터페이스여야 한다"라는 조건을 만족해야 한다.
- View.OnClickListener 인터페이스는 Java로 작성되어 있고, 추상 메소드가 onClick() 하나이기 때문에 이를 람다식으로 작성할 수 있다.
✏️ Data class
1. Data class
- Data class는 말 그대로 데이터를 담는 클래스이다.
data class Movie(
val name: String,
val genre: String,
val director: String,
val score: Float
)
fun main() {
val movie = Movie("Frozen 2", "Animation", "크리스 벅", 8.95F)
print(movie)
}
Movie(name=Frozen 2, genre=Animation, director=크리스 벅, score=8.95)
- data class의 요소들은 클래스의 프로퍼티처럼 이용 가능
- 컴파일 하면 자동으로 data class에서 toString(), hashCode(), equals(), copy() 등을 사용할 수 있음
- data class는 일반 클래스와 다르게 그 자체를 출력하면 주소값이 출력되지 않고 data class의 내용이 출력됨
✏️ Companion Object
1. Companion Object
- 자바의 static 대신 사용하는 것으로 정적인 변수나 함수를 선언할 때 사용
- private 프로퍼티나 메소드를 읽어올 수 있게 함
class Student private constructor(val id: Int, val name: String){
companion object {
fun create() = Student(1234, "minha")
}
}
fun main() {
val student = Student.create()
print("Id is ${student.id}. Name is ${student.name}.")
}
Id is 1234. Name is minha.
- companion object 내에서 변수를 사용할 수 있고 companion object에 이름을 붙일 수 있음
class Student private constructor(val id: Int, val name: String){
companion object StudentInfo {
val name = "minha"
fun create() = Student(1234, name)
}
}
fun main() {
val student = Student.StudentInfo.create()
val studentName = Student.StudentInfo.name
println("Id is ${student.id}. Name is ${studentName}.")
}
Id is 1234. Name is minha.
class Student private constructor(val id: Int, val name: String){
companion object StudentInfo: IdProvider {
override fun getId(): Int {
return 12345
}
val name = "minha"
fun create() = Student(getId(), name)
}
}
interface IdProvider {
fun getId(): Int
}
fun main() {
val student = Student.StudentInfo.create()
val studentId = Student.StudentInfo.getId()
println("Id is ${studentId}. Name is ${student.name}.")
}
Id is 12345. Name is minha.
✏️ Object
1. Object
- 클래스와는 다르게 싱글톤 패턴이 적용, 즉 실행할 때 딱 한번 만들어짐
- 불필요하게 메모리가 사용되는 것을 방지할 수 있음
data class Phone(val serialNum: Int)
object PhoneFactory {
val phones = mutableListOf<Phone>()
fun makePhone(serialNum: Int): Phone {
val phone = Phone(serialNum)
phones.add(phone)
return phone
}
}
fun main() {
val phone1 = PhoneFactory.makePhone(12345)
val phone2 = PhoneFactory.makePhone(67890)
println("phone1 is ${phone1}, phone2 is ${phone2},
phones size is ${PhoneFactory.phones.size.toString()}")
}
phone1 is Phone(serialNum=12345), phone2 is Phone(serialNum=67890), phones size is 2