[Kotlin 문법 종합] - Single-expression function, 싱글턴 (@@질문하기)
1. Single-expression function
: 람다식을 이용해 메소드를 간결하게 정리 가능
* 람다식 구조 : 다른 함수의 인자로 넘김 / 함수의 결과값으로 반환 / 변수에 저장 하는 함수
{매개변수1, 매개변수2... ->
코드
}
* 예시 1 : 세 개의 숫자를 받아 평균을 반환하는 함수(를 람다식으로 정의)
fun add(num1:Int, num2:Int, num3:Int) = (num1+num2+num3)/3
fun main(){
println(lambdaExample({x,y -> x+y}, 20, 30)) //람다식 함수를 인자로 넘김
}
fun lambdaExample(sum: (Int, Int) -> Int, a: Int, b: Int): Int = sum(a, b)
//위와 동일
fun lambdaExample(sum: (Int, Int) -> Int, a: Int, b: Int) : Int) : Int {
//자료형이 람다식으로 선언됨
return sum(a,b) //sum은 람다식의 표현문에 따라 a+b의 정수 결과를 리턴함
}
* 예시 2 : 동일한 로직을 메소드 선언 없이 저장하기
var add = {num1: Int, num2: Int, num3: Int -> (num1+num2+num3) / 3}
// -> 를 통해 = 없이 우측 코드를 가짐을 나타냄. 변수처럼!
println("평균값은 ${add(10,20,30)}입니다")
// 변수에 할당하는 람다식 변수 @@추가하기
fun main(){
var result : Int
val example = {x: Int, y: Int -> x * y} //일반 변수에 람다식 할당
result = example(10,30) //람다식이 할당된 변수는 함수처럼 사용 가능
println(result)
}
//300
val example: (Int, Int) -> Int //람다식의 자료형 선언
= {x: Int, y: Int -> x*y}
2. 싱글턴
: 메모리 전역에서 유일한 객체임을 보장 (모든 객체에 의해 공유되는 효과...)
- 싱글턴으로 만든 인스턴스는 메모리 전역에서 유일 & 위치정보가 고정됨. 동일
- 프로그램이 실행되는 시점에 바로 메모리에 로드됨
(+) 전역적으로 활용 가능, 다른 클래스들에서 쉽게 접근 가능
(+) 효율적인 메모리 활용 가능
(+) 객체 차원에서의 충돌 방지
//ex. 1개의 프린터기, 공동사용
companion, object로 구현
- 생성자 안 적어도 됨. 자바랑 다르네
?@JvmStatic 뭐지...281~
class KCustomer{
companion object{
const val LEVEL = "INTERMEDIATE"
@JvmStatic fun login() = println("Login")
}
}
@JvmStatic 애노테이션 : 자바 소스에서 코드를 해석할 때 Companion을 생략할 수 있게 함
KCustomer.login();
KCustomer.Companion.login(); //애노테이션 사용하지 않은 경우
@JvmField 애노테이션 : 프로퍼티를 자바에서 사용하고자 할 경우
//object 키워드를 사용한 방식
object OCustomer{
var name = "철이"
fun greeting() = println("Hello World")
val HOBBY = Hobby("Basketball")
init{
println("Init!")
}
}
//컴패니언 객체를 사용한 방식
class CCustomer{
companion object{
const val HELLO = "hello" //상수 표현
var name = "미애"
@JvmField val HOBBY = Hobby("Football")
@JvmStatic fun greeting() = println("Hello World")
}
}
class Hobby(val name: String)
fun main() {
OCustomer.greeting() //객체의 접근 시점
OCustomer.name = "기영"
println("name = ${OCustomer.name}")
println(OCustomer.HOBBY.name)
CCustomer.greeting()
println("name = ${CCustomer.name}, HELLO = ${CCustomer.HELLO}")
println(CCustomer.HOBBY.name)
}
- object로 선언된 OCustomer는 멤버 프로퍼티, 메서드를 객체 생성하지 않고도 . 으로 접근할 수 있음
- 단일 인스턴스를 생성해 처리하기 때문에 싱글톤 패턴에 사용됨
- object 선언 방식 사용 시 접근 시점에 객체 생성됨 -> 생성자 호출을 하지 않음 = object 선언 시 주/부 생성자 사용 불가
- 수정 가능
2024.03.15 - [언어/Kotlin] - [Kotlin 공부] object와 싱글톤, object와 compaion
[Kotlin 공부] object와 싱글톤, object와 compaion
dd
sugapowderjj.tistory.com
객체 생성하지 않고도 클래스 정보에 접근 가능
1) 생성자 호출하지 않는 경우
fun main() {
Bird.fly("참새") //객체 생성 없이 클래스 이름.메서드( )
}
object Bird {
fun fly(name:String) {
println("${name}가 날아요~")
}
}
class Person{
var id: Int=0
var name: String = "철이"
companion object{
var language : String = "Korean"
fun work(){
println("working")
}
}
}
fun main(){
println(Person.language) //인스턴스 생성하지 않고도 사용 가능
Person.language = "Engligh" //기본값 변경 가능
println(Person.language) //변경된 내용을 출력함
Person.work() //메서드 실행
//println(Person.name) //name은 컴패니언 객체가 아니니까 안됨
}
2) 생성자를 호출하는 경우
fun main() {
// trash와 같이 생성자에 매개변수 전달 가능
var singletonObject1 = MySingletonClass.getInstance(trash = 1)
singletonObject1.setNum(5)
println("num값은: ${singletonObject1.getNum()}")
// singletonObject2에서 num을 10으로 대입
var singletonObject2 = MySingletonClass.getInstance(trash = 1)
singletonObject2.setNum(10)
// singletonObject1의 num이 10으로 출력됨
// singletonObject1과 singletonObject2는 같은 객체를 공유하기 때문
println("num값은: ${singletonObject1.getNum()}")
}
class MySingletonClass private constructor() {
private var num:Int = 0
companion object {
@Volatile private var instance: MySingletonClass? = null
private var trash = 0
fun getInstance(trash: Int): MySingletonClass {
this.trash = trash
// 외부에서 요청왔을때 instance가 null인지 검증
if(instance == null) {
// synchronized로 외부 쓰레드의 접근을 막음
// 쓰레드는 다음챕터에서 소개합니다!
// 쓰레드간의 객체상태 혼돈을 막기위해 사용한다고 이해해주세요
synchronized(this) {
instance = MySingletonClass()
}
}
return instance!!
// 엘비스연산자와 뒷장에서배울 scope function을 이용하면
// 아래와같이 더욱 직관적인 코드 작성이 가능합니다
// return instance ?: synchronized(this) {
// // also는 호출한 객체를 it으로 넘김
// // instance가 null이라면 새로 생성하고 아니면 무시함
// instance ?: MySigletonClass().also {
// instance = it
// }
// }
}
}
fun setNum(num: Int) {
this.num = num
}
fun getNum(): Int{
return this.num
}
}