출처 : Tekhit Android App School / Soft campus 윤재성 강사님
🎉 중첩 클래스(Inner Class)
- inner 지시자를 사용해 클래스안에 작성하는 클래스
- 내부 클래스의 객체를 생성하려면 외부 클래스를 통해 참조해야 합니다.
class Outer1{
// 프로퍼티
var outerValue1 = 100
// 메서드
fun outerMethod1(){
println("Outer1의 outerMethod1")
// println("innerValue : $innerValue1")
// innerMethod1()
}
var innerValue1 = 200
fun innerMethod1(){
println("Inner1의 innerMethod1 입니다")
}
inner class Inner1{
var innerValue1 = 200
fun innerMethod1(){
println("outerValue1 : $outerValue1")
outerMethod1()
}
}
}
- 외부 클래스의 메소드인 outerMethod1( ) 에서 내부 클래스 요소를 사용할 수 없습니다.
- 외부 클래스의 객체의 생성이 내부 클래스 객체의 생성을 보장할 수 없기 때문에 외부 클래스에서 내부 클래스의 요소는 사용할 수 없습니다.
- 반대로 내부 클래스를 통해 구현한 객체 입장에선 외부 클래스의 객체가 생성되어 있다는 것을 보장 받을 수 있어 외부 클래스에 정의되어 있는 모든 멤버들을 사용할 수 있습니다.
🎉 익명 중첩 클래스
interface Inter1{
fun interMethod1()
fun interMethod2()
}
class TestClass1 : Inter1{
override fun interMethod1() {
println("TestClass1의 innerMethod1")
}
override fun interMethod2() {
println("TestClass2의 innerMethod2")
}
}
- 인터페이스나 추상 클래스는 이를 상속하는 메소드를 구현해 클래스를 만들어야 객체를 생성할 수 있습니다.
- 만약 이런 클래스를 통해 생성하는 객체가 하나 뿐이라면 익명 중첩 클래스를 사용하는 것이 편합니다.
val obj4 = object: Inter1{
override fun interMethod1() {
println("익명 중첩 클래스의 innerMethod1")
}
override fun interMethod2() {
println("익명 중첩 클래스의 innerMethod2")
}
}
- 클래스의 작성과 메스드의 오버라이딩, 객체 생성을 모두 한번에 수행할 수 있습니다.
- 단, 이름이 없는 1회용 클래스이기 때문에 이 클래스를 다른 곳에서 사용할 수 없습니다.
- object의 Type은 인터페이스 또는 추상 클래스여야만 합니다.
🎉 Null
객체의 주소값이 비어있는(null) 참조 변수에 접근을 시도하면 NullPointerException이 발생합니다. 코틀린에선 null 안정성을 확보할 수 있는 다양한 방법이 있습니다.
?. 연산자
- 객체가 가지고 있는 프로퍼티나 메서드를 사용할 때 쓰는 연산자 입니다.
- 변수에 null이 들어가 있으면 NullPointerException 오류가 발생하지 않고 null을 반환합니다.
- 메서드가 null 이면 메서드의 호출을 취소합니다.
fun main(){
val t11:TestClass1? = null
val t12:TestClass1? = TestClass1()
println("t11.testValue1 : ${t11?.testValue1}")
println("t12.testValue1 : ${t12?.testValue1}")
t11?.test1Method()
t12?.test1Method()
}
class TestClass1{
var testValue1 = 100
fun test1Method(){
println("TestClass1의 test1Method")
}
// 값을 반환하는 메서드
fun test2Method():Int{
return 100
}
}
!! 연산자
- null 을 허용하는 형태의 변수를 null을 허용하지 않는 형태로 변환합니다.
- null을 허용하는 변수에 저장되어 있는 값을 null을 허용하지 않는 변수에 담을 때 사용합니다.
- 이 때, null값이 들어 있다면 NullPointerException 오류가 발생합니다.
fun main() {
var a2:TestClass1? = null
// 변수에 null 값이 들어있는 상태에서 메서드를 호출한다.
//a2!!.test1Method()
// 오류가 발생한다(NullPointerException)
a2!!.test1Method()
}
엘비스 연산자 ( ?: )
- null 값을 허용하는 변수를 사용할 때 null이 들어가 있을 경우 객체 대신에 기본값을 반환합니다.
- 변수에 Null 값이 들어가 있을 경우 객체를 생성해서 반환해주는 작업을 할 때 사용합니다.
fun main(){
var t7: TestClass1? = null
var t8: TestClass1? = TestClass1()
var t9 = t7 ?: TestClass1()
var t10 = t8 ?: TestClass1()
println("t7 : $t7, t9: $t9")
println("t8 : $t8, t10: $t10")
}
class TestClass1{
var testValue1 = 100
fun test1Method(){
println("TestClass1의 test1Method")
}
// 값을 반환하는 메서드
fun test2Method():Int{
return 100
}
}
스마트 캐스팅
- 특정 조건을 만족하면 자동으로 현변환이 이루어 집니다.
- null을 허용하는 변수에 null 이 아닌 객체의 주소값이 들어가 있음을 확신 시켜주면 스마트 캐스팅이 발생하여 null을 허용하지 않는 타입으로 변환해줍니다.
- if문으로 null 여부를 검사해주면 null을 허용하지 않는 타입으로 스마트 캐스팅이 발생합니다.
- 단 if문을 벗어나면 다시 원래대로 돌아갑니다.
fun main() {
if(t1 != null){
t1.testMethod1()
}
if (t1 is TestClass1){
t1.testMethod1()
}
}
class TestClass1{
fun testMethod1(){
println("TestClass1의 testMethod1 입니다")
}
}
🎉 Casting
as
- 객체의 주소값을 가지고 있는 변수의 타입을 다른 클래스 타입으로 변환합니다.
fun main() {
val obj1:SuperClass1 = SubClass1()
val obj3 = obj1 as SubClass1
// ClassCastException
// val obj4 = obj1 as String
}
open class SuperClass1{
fun superMethod1(){
println("SuperClass1의 superMethod1 입니다")
}
}
class SubClass1 : SuperClass1(){
fun subMethod1(){
println("SubClass의 subMethod1 입니다")
}
}
- 클래스의 상속 관계에서 자식 클래스를 부모 클래스 타입으로 생성할 수 있습니다.
- obj1에는 자식 클래스를 사용해 만든 객체의 주소값이 들어있기 때문에 부모 클래스 타입의 obj1을 as를 사용해 자식 클래스로 타입으로 변환하여 obj3에 담았습니다.
- obj4 처럼 다른 클래스 타입으로 변환할 경우 ClassCastException 에러가 발생합니다.
is
- 왼쪽 피연산자가 오른쪽에 주어진 타입이면 true를 반환합니다.
- 왼쪽 피연산자의 정적 타입이 오른쪽 타입의 상위 타입인 경우에만 사용이 가능합니다.
- obj6은 자식 클래스로 생성하였지만 Type은 부모 클래스이므로 직접 자식 클래스의 메소드에 접근할 수 없습니다.
- is를 통해 자식 클래스 타입인지 검사하면 true일 경우, Smart Casting으로 검사 대상 타입으로 변환해줍니다.
fun main(){
val obj6:SuperClass1 = SubClass1()
// obj6.subMethod1()
if(obj6 is SubClass1){
obj6.subMethod1()
}
}
open class SuperClass1{
fun superMethod1(){
println("SuperClass1의 superMethod1 입니다")
}
}
class SubClass1 : SuperClass1(){
fun subMethod1(){
println("SubClass의 subMethod1 입니다")
}
}
- 객체를 생성했을 때 사용한 클래스가 무엇인지 확인할 수 있습니다.
- 객체를 생성했을 때 사용한 클래스의 부모 클래스도 확인할 수 있습니다.
fun main() {
val obj5 = SuperClass1()
val chk1 = obj5 is SubClass1
val chk2 = obj5 is SuperClass1
val chk3 = obj5 is Inter1
println("chk1 : $chk1")
println("chk2 : $chk2")
println("chk3 : $chk3")
}
open class SuperClass1{
fun superMethod1(){
println("SuperClass1의 superMethod1 입니다")
}
}
- 코틀린에서 사용하는 모든 기본 자료형은 클래스입니다.
val str1 = "100"
val number1 = str1.toInt()
if(number1 is Int){
println("정수로 변환되었습니다.")
}
val str2 = number1.toString()
if(str2 is String){
println("문자열로 변환되었습니다.")
}
GitHub - chanho0908/Tekit_Android_App_School: Tekit Android App School Kotlin Study
Tekit Android App School Kotlin Study. Contribute to chanho0908/Tekit_Android_App_School development by creating an account on GitHub.
github.com
'TEKHIT ANDROID SCHOOL' 카테고리의 다른 글
[TEKHIT] KOTLIN FUNCTION (0) | 2024.01.11 |
---|---|
[TEKHIT] Enum & SealedClass & Reflection (0) | 2024.01.11 |
[TEKHIT]Companion & Data Class & Generic (1) | 2024.01.10 |
[TEKHIT] Any & This Super (0) | 2024.01.10 |
[TEKHIT] Abstract & Interface (0) | 2024.01.05 |