이너 클래스를 사용할 땐 이너는 바로 객체 생성 할 수 없음 (아웃터 없이 사용할 까봐)
아웃터 클래스만이 이너 클래스를 객체로 만들수 있다
코틀린에서 이너클래스가 되려면 inner 키워드를 써줘야함
fun main(){
val obj = AAA()
//val obj2 = BBB() // 이너는 밖에서 인식 안됨
//이너 클래스는 외부에서 직접 객체생성 불가
//아웃터 없이 사용 할깨봐 이너는 직접 만들 수 없음
//이너 클래스 객체는 아웃터 클래스만 만들 수 있다
val obj2:AAA.BBB = obj.getBBBinstance()
obj2.show()
}
class AAA {
var a: Int = 0
fun show() {
println("AAA 클래스 show : $a")
}
//이너클래스 객체를 생성하여 리턴해주는 기능 메소드
fun getBBBinstance(): BBB {// 리턴 타입
return BBB()
}
// 위 코드 간결화
fun getBBBinstance() = BBB()
//이너 크래스
//코틀린에서 이너클래스가 되려면 inner 키워드를 써줘야함
inner class BBB {
fun show() { //상속 관계가 이니기 때문에 오버라이드 아님
//이너 클래스의 장점
//1. 아웃터의 멤버를 내것인양 사용
a = 100
println("아웃터 클래스의 멤버 a : $a")
//아웃터의 show 메소드를 호출하기
this@AAA.show() // this@MainActivity
//이너에서 아웃터 부르는 행위
}
}
}
아웃터의 show 메소드를 호출하기
this@AAA.show() // cf) this@MainActivity
이너에서 아웃터 부르는 행위
메인 액티비티의 this부를 때 많이 사용함
fun main() {
//2. 인터페이스
//객체 생성 불가 - 기능설계 안되어 있어서
//var c:Clickable = Clickable() // error
//인터페이스를 구현한 Test 클래스를 객체로 생성
var c:Clickable = Test() //up casting (뭘 위해 만들었는지 강조하기 위해 업캐스팅 함)
c.onclick()
println()
}
//2. interface 추상메소드만 가진 class
interface Clickable {
//abstract method - 이름만 있는 메소드
//abstract fun onclick() - abstract 생략 가능
fun onclick()
}
//인터페이스의 추상메소드들을 구현하는 별도의 클래스를 설계하고
//이 클래스를 객체로 만들어서 사용해야됨
// implements 키워드 대신 상속처럼 : 기호 사용
//인터페이스를 구현할 때는 상속과 다르게 인터페이스명 옆에 () 생성자 호출은 없음
class Test : Clickable {
override fun onclick() {
println("click!!!")
}
}
🔨 object
익명 클래스 객체를 만드는 키워드
기존 자바에서 익명 클래스 구현 방법
var c2:Clickable = new Clickable {};
fun main() {
//2-1. 익명 클래스
//다른 기능을 하는 또 다른 Clickable이 필요
//또 다시 Test 같은 새로운 class 를 명명하는 것이 싫음
//객체 생성 동시에 인터페이스를 그자리에서 구현하는 익명클래스 사용
//var c2:Clickable = new Clickable {}; //기존 자바에서 익명 클래스 구현 방법
//코틀린에서 익명 클래스 만드는 방법
// 익명 클래스 객체를 만드는 키워드 : object
var c2:Clickable = object : Clickable{
override fun onclick() {
println("눌러 눌러")
}
}
}
//2. interface 추상메소드만 가진 class
interface Clickable {
//abstract method - 이름만 있는 메소드
//abstract fun onclick() - abstract 생략 가능
fun onclick()
}
//인터페이스의 추상메소드들을 구현하는 별도의 클래스를 설계하고
//이 클래스를 객체로 만들어서 사용해야됨
// implements 키워드 대신 상속처럼 : 기호 사용
//인터페이스를 구현할 때는 상속과 다르게 인터페이스명 옆에 () 생성자 호출은 없음
class Test : Clickable {
override fun onclick() {
println("click!!!")
}
}
💡 어차피 전역변수가 있어서 만들지 않은 거 같지만 companion을 만든 이유는 소속감을 주기 위해 만든 거 같음
🔨 companion object {}
{} 안에 있는 멤버들은 이미 객체화 되어 있기 때문에 따로 객체 생성 없이 그냥 사용 가능, {} 안의 멤버들은 클래스명. 으로 접근!
fun main() {
println(Sample.title) //클래스명.멤버변수
println(Sample.show())
}
//4. 동반 객체 (자바 static 대체)
class Sample {
var a:Int = 10 //인스턴스 변수는 객체 생성 할 때만 쓸수 있음
//static var b:Int = 200 // -error : static 없음
companion object {
//이 안에 있는 멤버들은 이미 객체화 되어 있기 때문에 그냥 사용 가능
//단, Sample 클래스에 동반되어 있기 떄문에 클래스명이 요구됨
var title:String = "Hello"
fun show(){
println("동반 객체의 show()")
}
}
}
참조변수 만들때 코틀린은 반드시 초기화가 필요함
하지만 뷰는 onCreate() 될때 만들어지기때문에 늦은 초기화가 필요함
🧨 var 변수에만 사용
☝ 사용 특징
1) nullable 변수는 lateinit불가
lateinit var title:String? //에러
2) 기본 자료형(8개) 사용불가
lateinit var age:Int //에러 - 참조가 아니가 값이니 초기값 넣어라
3) val에는 사용 불가
fun main() {
//4-1) lateinit [var 변수에만 사용]
var h:Hello = Hello()
//println(h.name) //Exception 발생
h.onCreate() //초기화를 해줘야
println(h.name) // 객체 참조 가능
}
//4. 늦은 초기화
class Hello{
//4-1) lateinit
//var name:String - error 초기화 반드시 해야됨
//초기화를 나중에 하고 싶다면...
lateinit var name:String
fun onCreate(){
name = "sam" //이때 초기화
}
//lateinit 사용 특징
//1) nullable 변수는 lateinit불가
//lateinit var title:String? //에러
//2)기본 자료형(8개) 사용불가
//lateinit var age:Int //에러 - 참조가 아니가 값이니 초기값 넣어라
//3) val에는 사용 불가
}
by lazy 는 대입과 같은 것
🧨 val 변수에서만 사용
☝ 사용특징
1) 기본형 자료형도 가능
2) nullable도 가능
3) 조건값으로 값 대입도 가능함 ( { } 영역이 있으니까 )
fun main() {
//4-2) by lazy [val 변수에서만 사용]
println(h.addr) //add는 객체 생성 할 때 초기화
println(h.address) //지금 이 순간 초기화 됨
println(h.tel)
}
//4. 늦은 초기화
class Hello{
//4-2) by lazy [val 변수에서만 사용]
//val address:String //에러
val address:String by lazy { //이 변수가 처음 사용 될 때 초기화 됨
"seoul"
}
val addr:String = "busan" //이 순간 초기화 됨
val tel:String by lazy {
println("늦은 초기화")
"010-2222-1111"
}
//by lazy 특징
//1) 기본형 자료형도 가능
val age:Int by lazy { 20 }
//2) nullable도 가능
val message:String? by lazy { "Hello" }
val message2:String? by lazy { null }
//3) 조건값으로 값 대입도 가능함
val message3:String? by lazy {
if (age < 20) "미성년자"
else "성인"
}
//4) var 에는 사용 불가능
//var sss:String by lazy { "aaa" } // error
}