- Today
- Total
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 탐탁노트북파우치
- 삼성파우치
- 백준
- MVVM
- 비트마스킹
- kotiln
- 안드로이드#코틀린#디자인패턴#싱글턴패턴#개발#앱개발
- 투포인터
- bitmasking
- lateinit
- DataBinding
- 자바
- 등산로조성
- 코틀린
- 싸피
- Kotlin
- Higher-Order
- 코딩테스트
- 아키텍처패턴
- nullalble
- 알고리즘
- ssafy서울
- 삼성청년sw아카데미
- Java
- #충무로맛집#골목식당#스테이크#
- 안드로이드
- Android
- 삼성역량테스트
- tomtoc
- 탐탁삼성파우치
공상하는 개발자
[코틀린] 코틀린 익숙해지기 3탄(데이터클래스,중첩클래스,람다 등) 본문
데이터 클래스 (data class)
-> 내부에 특별한 로직이 있는 함수가 없이 데이터만을 포함할 수 있는 클래스
코틀린에서는 이런 클래스들을 조금 더 편리하게 사용할 수 있도록 데이터 클래스를 제공한다.
데이터 클래스는 data 예약어(키워드)를 이용해서 선언한 클래스이다.
※ 데이터 클래스 선언 형식
data class User(val name : String, val age: Int)
★ 일반 클래스와 비교
- data 키워드 사용
- 주 생성자를 선언
- 주 생성자의 매개 변수는 최소 하나 이상이어야 한다.
- 모든 주 생성자의 매개변수는 var 또는 val로 선언해야 한다.
- abstract, open, sealed, inner 등의 예약어를 사용할 수 없다.
에러의 경우
//data class user() //주 생성자의 매개 변수가 없다.
//data class User2(name: String) //매개변수에 val/var 선언이 안되어 있음.
//data abstract class User3(val name: String, val age: Int) //abstract 키워드 사용
//data class User4(val name: String, id: Int) //두 번째 매개변수에 val/var 선언이 안 되어있음.
♣ 데이터 클래스의 함수
- 데이터 클래스는 클래스 내에 데이터와 관련된 다양한 함수를 제공한다.
- 따라서, 개발자가 클래스 내에 선언하지 않아도 자동으로 다음과 같은 함수를 제공받는다.
- equals() / hashCode / toString()
- copy()
equals()를 이용한 데이터 비교(같은 data class 끼리 비교)
class Product(val name:String,val price:Int)
data class User1(val name: String,val age:Int)
fun main() {
// 일반 클래스의 equals()함수는 객체를 비교를 한다.
var prod1 = Product("상품1", 10000)
var prod2 = Product("상품1", 10000)
println(prod1.equals(prod2)) //false 출력
// 데이터 클래스의 equals()함수는 객체를 비교하지 않고 객체의 데이터를 비교한다.
val user1 = User1("홍길동", 50)
val user2 = User1("홍길동", 50)
println(user1.equals(user2)) //true 출력
val user3 = User1("홍길동",40)
println(user1.equals(user3)) //false 출력
}
equals() 를 이용한 데이터 비교(다른 data class 끼리 비교)
data class Student(val name:String,val age:Int)
data class Employee2(val name: String,val age: Int)
fun main() {
//equals()함수는 서로 다른 데이터 클래스 객체는 데이터를 비교하지 않는다.
//같은 데이터 클래스 객체일 때만 데이터를 비교한다.
val student = Student("홍길동",22)
val employee = Employee2("홍길동",22)
println(student.equals(employee)) //false 출력
}
equals() 를 이용한 데이터 비교(다른 프로퍼티 값을 가진 data class끼리 비교)
data class Professor(val name: String, val subject: String) {
var email: String = "aaa@aaa.net"
}
fun main() {
//데이터 클래스의 equals()함수는 주 생성자의 매개변수 값만 비교한다.
//클래스 내에 있는 프로퍼티는 비교하지 않는다.
val professor1 = Professor("홍길동", "컴퓨터공학")
val professor2 = Professor("홍길동", "컴퓨터공학")
professor2.email = "bbb@bbb.net"
println(professor1.equals(professor2)) //true 출력!
}
toString() 함수 소개
class Teacher(val name: String, val age: Int)
data class Teacher2(val name: String, val age: Int) {
val email: String = "test@test.com"
}
fun main() {
var teacher = Teacher("홍길동", 55)
println(teacher.toString())
// 데이터 클래스의 toString()함수는 객체가 가지고 있는 데이터 값을 반환한다.
// 이 때의 값은 주 생성자의 프로퍼티 값만을 반환한다.
// 클래스 내부에 있는 프로퍼티 값은 출력하지 않는다.
// toString() 함수는 일반적으로 디버깅시에 로그 출력용으로 많이 사용한다.
//객체의 데이터가 정상적으로 대입 됐는지 확인 하는 용도로 사용한다.
var teacher2 = Teacher2("홍길북", 33)
println(teacher2.toString())
}
componentN() 함수
-> 데이터 클래스에서 제공하는 componentN() 함수
데이터 클래스의 프로퍼티에 값을 가져올 때 프로퍼티의 이름을 사용하는 경우가 있고, componentN() 함수를 이용할 수도 있다.
※ componentN() 함수는 component1(), component2().... 식으로 사용하는데,
주 생성자의 프로퍼티가 2개인 경우에는 component1(), component2() 함수가 자동으로 만들어진다.
주 생성자의 프로퍼티가 2개인 경우에는 component1(), component2(), component3() 함수가 자동으로 만들어진다.
data class Car(val name: String, val speed: Int)
fun main() {
var car = Car("카1", 200)
println(car.name) //카1 출력
println(car.speed) //200 출력
println(car.component1()) //카1 출력
println(car.component2()) //200 출력
}
근데 이렇게 사용하면 그냥 사용하는 것보다 직관적이지 못하고 비효율적이다.
그렇다면 언제 쓰는 것이 효율적일까??
데이터 분해 선언
// 데이터 분해선언(Destructuring declarations)
data class Flower(val name: String, val price: Int)
fun main() {
var flower = Flower(price = 2000,name = "장미")
val (name,price) = flower //데이터 분해 선언
println("name: $name, price: $price") //name: 장미, price: 2000 출력....
}
copy() 함수 소개
데이터 클래스에서 제공하는 copy() 함수 : 이름 그대로 객체를 복사해서 다른 개체를 만들어주는 함수
객체의 일부분의 데이터만 변경해서 다른 객체를 만들 때 유용하게 사용할 수 있다.
data class Product2(val name: String, val price: Int)
fun main() {
var prod = Product2(price = 10000, name = "상품1")
println(prod.toString()) //Product2(name=상품1, price=10000) 출력
var prod2 = prod.copy(name = "상품2")
println(prod2.toString()) //Product2(name=상품2, price=10000) 출력
}
중첩 클래스
-> 클래스 안에 클래스
쓰는 이유 : class 안의 private로 선언된 프로퍼티나 함수에 접근해야 할 때 사용한다.
중첩 클래스
class Outer {
var num: Int = 100
fun outerfun() {
println("outerfun.....")
}
class Nested {
fun greeting() = println("안녕하세요!")
// Nested 클래스에서 Outer 클래스에 있는 멤버에 기본적으로 접근이 불가능하다.(private 이 아닌데도 불가)
// fun nestedfun() = println(num) // 에러 발생
}
}
inner class 구현
class Outer2 {
private var num: Int = 100
fun outerfun() = println("Outerfun의 outerfun() 이다... ...")
inner class Nested {
val name: String = "홍길동"
fun myFunc() {
println("Nested의 myFunc()... ...")
num = 200
outerfun()
}
}
fun createNested():Nested{
return Nested()
}
}
fun main() {
val obj:Outer2.Nested = Outer2().Nested()
val obj2:Outer2.Nested = Outer2().createNested()
println(obj.name) //홍길동 출력...
println(obj2.name) //홍길동 출력...
obj.myFunc() //Nested의 myFunc()... ...
//Outerfun의 outerfun() 이다... ...
}
내부 클래스에서 바깥 클래스 변수, 함수 사용하기
class Outer3(private var aa: Int) {
fun getInfo() {
println(this.aa)
}
inner class Inner(private val bb: Int) {
fun getInfo() {
// 내부 클래스는 기본적으로 바깥 클래스를 가리키는 참조변수를 가지고 있다.
// this@외부클래스명
this@Outer3.getInfo()
println(this.bb + this@Outer3.aa)
}
}
}
fun main() {
val outer3: Outer3 = Outer3(100)
val inner: Outer3.Inner = outer3.Inner(50)
inner.getInfo()
}
람다 표현식
-> 함수 프로그래밍 언어에서 코드의 간결함을 주목적으로 한다. ( 함수 축약형)
※ 일반 함수 형식
fun 함수 이름(매개변수) { 실행 코드들 }
일반 함수의 축약형 : 람다식
{ 매개변수 -> 실행코드들 }
★ 람다 함수의 규칙
- 람다 함수는 항상 {} 감싸서 표현해야 한다.
- {} 안에 -> 연산자가 있으며, -> 왼쪽에는 매개변수, 오른쪽에는 실행코드들이 위치한다.
- 매개변수 타입을 선언해야 한다. 추론할 수 있을 때는 생략할 수도 있다.
- 함수의 반환 값은 실행코드들에서 마지막에 표현한다.
→ 람다식은 익명 함수여서 호출하여 이용할 수가 없다.
따라서, 주로 변수에 대입을 해서 사용을 하는데, 변수를 사용하지 않고 람다 함수를 호출하려면 다음과 같이
{ println("Hello")}() // 람다함수를 만들자마자 호출하는 예
run { println("Hello") } // 람다함수를 만들자마자 호출하는 예
// 매개변수가 없는 람다 함수
val sum = { 100 + 100 } // -> 생략할 수 있다.
// 함수의 실행코드가 여러 줄일 때
val sum = { x: Int, y: Int ->
println("sum() 호출 ...")
x + y // 리턴 표현식
}
● 함수 타입 : 매개변수의 형식과, 리턴 타입의 형식, 몇 개의 매개변수를 갖는지.... 명시하는 것
fun myFunc(x: Int, y: Int):Boolean{
return x > y
}
val lamdaFunc: (Int) -> Int = { : Int -> x * 2 }
☞ it은 매개변수가 하나일 때 별도의 매개변수를 선언하지 않고 사용할 수 있는 키워드
val lamdaFunc: (Int) -> Int = { x -> x + 10 }
//식을 it을 이용해서 표현하면 다음과 같다.
val lamdaFunc: (Int) -> Int = { it + 10 }
❗️it은 타입이 정의되어 있는 곳에서만 사용할 수 있다.
val lamdaFunc = { it * 10 } // 에러 발생
'개발 > 코틀린' 카테고리의 다른 글
[Kotlin/JAVA] JSONObject, JSONArray 이해하기 (0) | 2020.08.22 |
---|---|
[코틀린] 코틀린 익숙해지기 4탄(제네릭, 고차함수, 애노테이션 등) (0) | 2020.03.22 |
[코틀린] 코틀린 익숙해지기 2탄 (object, inline 함수 등) (0) | 2020.03.05 |
[코틀린] 코틀린 익숙해지기 1탄 (확장함수, 클래스, 인터페이스 등) (0) | 2020.02.28 |