- 클래스(Class)
- 테스트케이스
- ~(test) 패키지는 안드로이드 기능과 상관없는 java or kotlin 코드를 테스트
- ~(androidTest) 패키지는 안드로이드 환경과 연관된 코드를 테스트
package com.example.kotlinsample
import org.junit.Assert
import org.junit.Test
class KotlinTest {
@Test
fun test1(){
// 예측결과와 실제결과가 동일하지 않는다면 테스트를 실패시키는 함수
Assert.assertEquals(4, 2 + 2)
}
}
- 프로퍼티(Property) / 필드(Field)
- 필드(Field)는 클래스에 선언되어 있는, 클래스 변수가 아닌 인스턴스 변수를 의미
- 프로퍼티(Property)는 Field와 외부에서 접근 가능한 Getter 또는 Setter 가 있는 경우 / Field 와 접근 가능한 Getter, Setter의 조합
- 코틀린은 실제로 Field 를 사용하지 않는다.
class Test(val name: String) {
// 나이
var age: Int = 0
// 닉네임 - 소문자만 허용
var nickname: String = ""
set(value) {
// field 는 Setter 의 대상이 되는 field 를 의미
field = value.toLowerCase()
}
}
- 클래스 상속
- 코틀린의 클래스는 기본적으로 상속이 불가
- 상속은 반복되는 중복 코드를 줄여 주는 객체 지향 프로그래밍 핵심 기법
- 2가지 측면에서 접근 가능
- 코드 구현에 대한 상속 / 인터페이스 집합에 대한 상속
- 인터페이스 상속은 다중 상속에서 자유롭지만 구현 상속은 다중 상속을 하는 경우 문제점이 생긴다.
- 취약한 기반 클래스 문제( fragile base class ) : 하위 클래스에서 상위 클래스의 메소드를 오버라이딩하면서 발생하며, 클래스를 사용하는 코드에서는 클래스의 실제 구현에는 관심을 가지지 않아야 하기 때문
- 캡슐화의 주요 목적 중 하나는 클래스를 사용하는 측면에서 해당 클래스의 구체적인 사항을 모르게 하는 것
- 구체적인 구현 클래스를 알아야만 한다면, '캡슐화가 깨졌다' 라고 본다.
- java 에서 상속을 금지하려면, final 키워드 사용 / public final class ~ / final public int ~
- 코틀린은 상속 불가 / 허용하려면 open 키워드 사용 / open class ~ / open fun ~
- 클래스 위임
- 객체 지향에서 위임이란 클래스의 특정 기능들을 대신 처리해 주는 것
- 위임은 코드를 재사용하면서도 취약한 기반 클래스 문제( fragile base class ) 를 해결할 수 있는 방법 중 하나.
- 데코레이터( Decorator ) 패턴 : 특정 클래스의 기능에 추가 기능을 덧붙이는 방법
// Decorator pattern
// ISword.java
public interface ISword {
public void equip();
}
// Sword.java
public class Sword implements ISword {
String name;
public Sword(String name) {
this.name = name;
}
@Override
public void equip() {
System.out.println( name + "검~" );
}
}
// MagicSword.java
public class MagicSword implements ISword {
ISword iSword;
public MagicSword(ISword iSword) {
this.iSword = iSword;
}
@Override
public void equip() {
play();
iSword.equip();
}
public void play() {
System.out.println("play~");
}
public static void main(String[] args) {
Sword sword = new Sword("마법");
new MagicSword(sword).equip();
}
}
- 코틀린은 'by' 키워드를 사용하여 위임을 쉽게 할 수 있다.
class DelegatingArrayList<T>(val innerList: MutableCollection<T> = mutableListOf()) : MutableCollection<T> by innerList {
...
}
- 프로퍼티 위임
- Getter, Setter 연산자를 위임할 수 있게 해주며, 3가지 방법을 제공
- lazy properties : 값의 초기화를 처음 프로퍼티를 사용할 때 초기화( lazy )
- observable properties : 프로퍼티에 값이 변경되면 옵저버에게 알려 줍니다.( observable )
- storing properties : 필드가 아닌 맵에 속성을 저장( map )
class DelegateString {
// Setter 에서 호출된 값을 저장할 변수
var text = ""
operator fun getValue( thisRef: Any?, property: KProperty<*>): String {
return text
}
operator fun setValue thisRef: Any?, property: KProperty<*>, value: String): String {
// 대문자로 변경하여 저장
text = value.toUpperCase()
// Setter 에 호출될 때의 문자열과 변경 후 문자열을 프린트
println( "$value ==> ${text}" )
}
}
class User {
// 닉네임은 DelegateString 클래스에 위임
var nickname by DelegateString()
// lay 위임은 val 키워드로 선언되어야만 가능함
val httpText by lazy {
println("lazy init start")
InputStreamReader(URL("https://..").openConnection().getInputStream()).readText()
}
// name 프로퍼티 값이 변경될 때 마다 자동으로 observable 의 코드가 실행된다.
var name:String by Delegates.observable(""){
property, oldValue, newValue ->
println( "기존값: ${oldValue}, 새로적용될값: ${newValue}" )
}
}
// Animal 클래스는 map 객체를 생성자에서 받는다.
class Animal(val map:MutableMap<String, Any?>) {
// 프로퍼티를 map 객체로 위임한다.
// map 객체에서 값을 읽고, 값을 변경하는 map 객체에서 값이 변경된다.
var name:String by map
var age:Int by map
}
- operator : 연산자를 의미
- Singleton 패턴 : 객체의 생성을 제한하여 한 개의 인스턴스만 생성되도록 하는 것
- object 키워드 : 해당 클래스가 싱글턴임을 알려준다.
object SingletonKotlin {
fun log(text:String){
println(text)
}
}
- data 키워드 : toString() , eqauls(), hashCode() 등의 함수를 자동으로 생성해 주는 Data클래스를 지원
data class Test( var name:String , var des:String )
- 클래스의 가시성 변경자
- 클래스의 메소드 혹은 필드에 대해 접근을 허용하는지 결정하는 역할
- java ------------------------------------------------------------------
- default( 기본 가시성 ) : 같은 패키지에서 접근 가능
- private : 클래스 내부에서만 사용 가능하며 외부에 비공개
- protected : 클래스와 상속받은 하위 클래스에서만 사용 가능
- public : 외부에서 모두 접근 가능
- kotlin ------------------------------------------------------------------
- internal : 같은 모듈에서 접근 가능 -> 자바에서는 public 으로 인식
- private : 같은 파일에서만 접근 가능
- protected : 최상위 선언에서는 사용 불가
- public( 기본 가시성 ) : 모든 곳에서 접근 가능
- 모듈 : 한꺼번에 컴파일되어 묶이는 하나의 프로젝트 단위
- 내부 클래스와 중첩 클래스
- 내부 클래스 : 클래스 내부에 그냥 class 를 선언하는 경우
- 중첩 클래스 : static 이 붙은 경우
- 차이점 : 외부에 있는 클래스와 생명 주기가 같은가 아닌가 로 구분
- 코틀린은 클래스 내부에 클래스를 선언하는 경우 중첩 클래스가 된다.
- 코틀린에서 내부 클래스로 선언하기 위해서는 inner class 로 선언
class Test {
val field1 = 0
// 코틀린은 내붕 클래스를 선언하면 중첩클래스가 됨
class NestedClass {
// 중첩 클래스에서는 외부 클래스 속성에 접근 불가
// val myField = field1
}
inner class InnerClass {
// 내부 클래스에서는 외부 클래스의 속성에 접근 가능
val myField = field1
}
}
* 코틀린에서 클래스의 프로퍼티는 val 의 경우 Getter 가, var 의 경우 Getter, Setter 가 자동 생성된다.
* 필드란 '인스턴스 변수'를 의미하고 프로퍼티란 '필드와 접근자( Getter , Setter )의 조합'을 의미한다.
* 코틀린의 프로퍼티는 접근자에 의해 결정되며, 필드를 사용하지 않는다.
* 코틀린은 클래스의 접근자에서 자신의 프로퍼티에 접근하기 위해 'field' 키워드를 사용하고, 이것을 'Backing Field' 라고 한다.
* 코틀린의 클래스는 기본적으로는 상속이 닫혀 있고, 상속을 허용하려면 'open' 키워드를 사용해야 한다.
* 코틀린은 클래스를 위임하기 위해 'by' 키워드를 사용할 수 있다.
* 코틀린은 프로퍼티도 위임이 가능하며, 위임을 하기 위해서는 역시 'by' 키워드를 사용한다.
* 코틀린의 프로퍼티 위임은 Getter , Setter 연산자를 구현한 클래스로 위임하거나, 표준 라이브러리에서 제공하는 'lazy, observalbe, map' 등으로 위임할 수 있다.
* 코틀린은 자주 사용되는 '싱글턴(Singleton)' 패턴을 대체하는 'object' 클래스를 사용할 수 있다.
* 코틀린의 'Data' 클래스에서는 'toString , equals , hashCode' 메소드가 자동으로 구현된다.
* 코틀린의 클래스는 Java 와 가시성이 일부 다르다. 특히 코틀린은 package 변경자가 없고, 모듈 가시성인 'internal'을 지원한다.
* 코틀린은 클래스 내부에 클래스를 선언하는 경우 기본적으로 '중첩 클래스'가 된다. Java 와 같이 '내부 클래스'로 선언하려면 'inner' 키워드를 사용한다.
'IT > Android(비공개)' 카테고리의 다른 글
[Android] View / Theme (0) | 2020.03.05 |
---|---|
Activity / Intent (0) | 2020.03.04 |
Android-studio / svn 연결 (0) | 2020.03.04 |
4. Kotlin(코틀린)_3 (0) | 2020.03.02 |
2. Kotlin(코틀린)_1 (0) | 2020.02.20 |
1. Android 기본 (0) | 2020.02.07 |
Android 재시작 (0) | 2020.02.07 |