1. Inteopeiseu (interface)reul contractro bogi
Sangsok (inheritance)e daehae cheoeum baeul ttae, ireon kkeutnaeju-neun gibun-i deulgo neun: “O, base classreul mandeulgo geugoseo buteo da sangsokbat-eul su itgetne!”. Geureon gibun-eun daebudae cheoeum peurojekteu han beon hamyeon kkeutnammida. Geuttae alge doejyo: “yusa-ham”eun jeongmal daleul su itdamnida. Chaek-gwa sayongja (user)neun seoro daleumnida (deiteoga dareum). Hajiman gakkeumeun du gae da “idreul gajil jul ara-ya” hamnida. Gyeolje (payment)wa jichul (expense)do chincheok-i anijiman, du gae da “bogoseoeseo han julmunjaro boyeojul jul ara-ya” hal ttaega it습니다.
I ttae inteopeiseuga bitnampnida: inteopeiseuneun “mueos-in-ga”ga anira “mueoseul hal su inneun-ga”reul seolmyeonghamnida.
Saram-ui biyuro gandanhi malhamyeon: sangsok-eun “~ui jongryu-ida” (goyangi-neun dongmul-ui han jongryu), inteopeiseuneun “~reul hal jul anda” (goyangi-neun meow()hal jul am, robotdo “myaung”hal jul alge mandeul su it-eum — geureoke hagi-ro gyeoljeonghamyeon… geurigo nugudo geugeol mag-eul gwolliga eopseumnida).
Kotlineseo inteopeiseuneun contractimnida. Contractran: “ne-ga jasin-eul X라고 malhamyeon, ne-neun ireon hamssu-wa/ttoneun sokseong-eul bangeun-ina jeong-eul haeya 한다”reul tteuthamnida. Geureodo inteopeiseuneun geugeol eotteoke halji-e daehaeseoneun geoui malhaji 않습니다.
2. Inteopeiseu seoneon-gwa keullaeseueseo-ui silhyeon
Contractreul seoneonhago geuge “seomyeng”hagi
Ije Kotlin-i chinjeolhage boineun sungan-i ol geosimnida: inteopeiseuneun saeng-gakboda deo swipge sseumnida. interfacereul seoneonhago, geu aneseo silhyeoni hal su isseoya haneun geotdeul (hamssu-wa sokseong)reul yeolgeo-hamyeon doemnida. Geu daeum eotteon keullaeseudun keullaeseu ireum dwie : InterfaceNamereul buchyeoseo “contracte seomyeng”hal su itseumnida.
Gajang minimalhan yepje-ro sijakhaebopsida — “gaeche-eun 식별자 (identifier)reul gajinda”neun contractimnida.
interface Identifiable {
val id: String
}
class User(override val id: String, val name: String) : Identifiable
Yeogiseo myeot gaji important pointeureul jibeogo gaja면 좋습니다.
Cheotjjae, inteopeiseu 안의 val id: Stringeun “field”ga animnida. “memory cell”, “munja yeoreul damneun sangja”do 아닙니다. Geugeon jeongmalro yogu-sahang-imnida: “neoneun ide jeopgeunhal su isseoya 한다”.
Duljjae, User keullaeseuneun primary constructor 안에서 override val id: Stringro yogu-sahang-eul gopgeunhi manjoekhamnida. Ige aju pyeonrihago ilgi swip-eun seutail-imnida: eotteon fieldga contract-ui ilbuginji chotnun-e bo입니다.
Seotjjae, inteopeiseuneun () gat-eun goekho-ga eopseumnida: inteopeiseuneun jikjeob gaecheoreul saengseonghal su eopseumnida. Geugeon geunyang “rule set”reul seolmyeonghaneun geot-ppunimnida.
Chu-sang metodeu: “silhyeonhaetdamyeon — kkok sseoya 한다”
Inteopeiseuneun jaju “i taibeun ireon chaegim-i itda”ran saeng-gag-eseo sijakhamnida. Chaegim-eul gajang jikjeobjeogeuro pyohyeonhaneun bangbeob-eun momchega eomneun hamssureul seoneonhaneun geotimnida. Geureom geu hamssuneun abstractga doego, silhyeoni kkodeul sseoya 합니다.
Ye-reul deureo, “insa-hal jul anda”neun contractreul mandeureobopsida.
interface Greeter {
fun greet(name: String): String
}
class FriendlyGreeter : Greeter {
override fun greet(name: String): String = "Annyeong, $name!"
}
overridereul ppaeteurimyeon 컴파일러가 jageunhi neomeogaji 않습니다. Geurigo i geot-i Kotlin-ui choegoui jangjeom jung hanaimnida: “eojjeoda boni inteopeiseureul geui silhyeon”haneun sasil-eul heoyonghaji 않습니다. Yeogin contractreul manjoekhage doneun-ga, an doneun-ga, du gaji ppunimnida.
maineseo jageun chekeureul haebomyeon sayong bangbeobi baro nukkyeojil geosimnida:
fun main() {
val g: Greeter = FriendlyGreeter()
println(g.greet("Kotlin")) // Annyeong, Kotlin!
}
Jom jomyeonghaebol jeom: byeonsu gui taib-eun FriendlyGreeterga anira Greeterimnida. Ige gwangyom haneun geot-i anigo, contract-ui haeksim-imnida. Urineun guchejeok keullaeseu-reul tonghae ilhaneun 게 아니라, “greethal jul 안다”는 약속을 통해 일합니다.
3. Inteopeiseu-ui sokseong-gwa silhyeon bangbeop
Inteopeiseu-ui sokseong-eun choboja-deuri gajang jaju heundeulrineun bu-bun jung hanaimnida. Intuitively “val idmyeon eodienga munjayeol-i jeojangdoegetji”라고 saeng-gakhaegi swipseumnida. Hajiman geureoji 않습니다.
Inteopeiseuneun sokseong jonjaereul yoguhal su itjiman, geu gap-eul eotteon bangsik-euro jeojanghara-go gangjehal sun eopseumnida. Silhyeon-eun 값을 field에 저장할 수도 있고, 필요할 때마다 계산할 수도 있습니다.
Han 가지 yogu-sahang-eul se gaji bangbeop-euro silhyeonhaneun yepjereul bopsida.
Field에 저장 (gajang ilbanjeog-in bangbeop)
interface Identifiable {
val id: String
}
class Expense(override val id: String, val title: String) : Identifiable
Expenseneun idreul jeongmalro sokseong-euro jeojanghamnida (backing fieldga saenggigil geosimnida).
Gyesan sokseong (jeojang eopsi)
interface Identifiable {
val id: String
}
class Session(private val token: String) : Identifiable {
override val id: String
get() = "session:$token"
}
Yeogiseo idneun getterro mae번 계산됩니다. idreul wihan byeoldo-ui fieldga eopseul sudo its습니다.
varreul inteopeiseu-eseo: ilgiwa sseugi (read/write) contract
Inteopeiseuneun varreul yoguhal sudo itseumnida — jeuk, ilgiwa sseugireul da yoguhaneun geosimnida. Hajiman i geos-eun joshimhae-ya 합니다: silhyeondeul-eul byeongyeong 가능 (mutable)hage mandeureo beorimyeon, geugeon hangsang joh-eun seontaeg-i anil su its습니다.
interface Renameable {
var title: String
}
class Note(override var title: String) : Renameable
I keullaeseuneun getterwa setterreul da 제공haeya 합니다. Geurigo majimak-euro han beon deo: inteopeiseuga jeojanghaneun 게 아니라, silhyeoni jeojang합니다.
Chai-reul han눈에 jeongrihae bogi wihae jageun pyoreul bopsida:
| Inteopeiseu-eseo sseoyeojin geot | Uimi | Gap-i jomhaneun got |
|---|---|---|
|
“xreul ilgeul su itda” | silhyeon (ttoneun gyeseon) |
|
“xreul ilgo, sujeonghal su itda” | silhyeon |
|
“hamssuneun pilyosu” | silhyeon-eseo kodeu |
|
“default dongjak-i itda” | inteopeiseu-eseo kodeu |
4. Default silhaeng: contract 안에 gibongeul neohgi
Ije Kotlin-i eomcheongnan geos-eul “jogeum munmyeonghage” haeju-neun bu-bun-imnida: inteopeiseu 안에서도 momchega inneun hamssureul sseul su itseumnida. Ireohge momchega inneun hamssuneun default silhaengi doeb니다: keullaeseuga gobaekjeok-euro overridehaji anado, geu dongjag-eul geunyang sangsokbadeul su 있습니다.
Kotlin munseo-eseoneun geugeon geunyang ireon moseup-imnida: inteopeiseuneun metodeu silhaeng-eul pohamhal su itda ( interface Polygon { fun draw() { ... } } gat-eun yepje).
Uri-ui gyoyuk-yong console aep (jichul tracker)eseo, enteeti-deul-eul “예쁘게” chulryeokhago sipgo, “jashin-eul han julmunjaro boyeojul su itda”neun gongtong contractga pilyoh다고 haebopsida. Inteopeiseureul mandeureobopsida:
interface RenderableLine {
fun renderLine(): String
}
Hajiman ajik-eun dan순히 abstract chaegim-ppunimnida. Jom deo jaemi-issge mandeureobopsida: contract-e sokseong-eul neohgo, renderLine()e defaultreul juseyo.
interface TitledAmount {
val title: String
val amount: Double
fun renderLine(): String = "$title: $amount"
}
Yeogiseo renderLine()eun contractga 보장하는 geot-man sayonghamnida: titlegwa amount입니다. Ige joheun default silhaeng-ui haeksim gyuchikimnida: inteopeiseuga 말하지 않는 “sumgyeojin” yogeul haeseoneun 안 됩니다.
Ije keullaeseuneun geunyang “seomyeng”man haedo 됩니다:
class Expense(
override val title: String,
override val amount: Double,
) : TitledAmount
Geureom kkeut — Expenseneun imi renderLine()hal jul 압니다.
Hwaginhaebopsida:
fun main() {
val e = Expense(title = "Coffee", amount = 3.5)
println(e.renderLine()) // Coffee: 3.5
}
Jungyohan nuance: default metodeuneun “게으른 사람을 위한 기능”i 아닙니다. Gongtong dongjag-eul contract gakkaie dwo-seo, modeun silhyeoni “gibonjeok-euro” gat-eun haengdong-eul 하게 만들고, dareun bu-bun-eun 명시적으로 드러나게 하는 bangbeop입니다.
5. Inteopeiseureul typeuro: beom-yong hamssu
Inteopeiseuneun hamssu parameter-ro badeugo, result-ro doerimyeon jinjja yuyonghaejimnida. Geureom kodeuga teukjeong keullaeseu-e deureobutji 않게 됩니다.
Ye-reul deureo, han julmunjaro renderhal jul 아는 eotteon gaecheu-deul-ido mogeul chulryeokhaneun hamssureul sseobopsida.
fun printLines(items: List<RenderableLine>) {
for (item in items) {
println(item.renderLine())
}
}
Ije uri-ui jichul model-eul i contract-e matchoebopsida. Ireohge 할 수 있습니다 (metodeu-reul myeongsi-jeogeuro silhyeon):
data class Expense(
val id: String,
val title: String,
val amount: Double,
) : RenderableLine {
override fun renderLine(): String = "[$id] $title — $amount"
}
Jal doeneunji bopsida:
fun main() {
val items = listOf(
Expense("e1", "Coffee", 3.5),
Expense("e2", "Transit", 2.75),
)
printLines(items)
// [e1] Coffee — 3.5
// [e2] Transit — 2.75
}
Kotlin-ui “gibun joeun dangdangham”e ju목haeseo boseyo: List<Expense>reul List<RenderableLine>reul gidaryeoneun got-e jeondalhal su itsseumnida. Wae냐하면 Expense : RenderableLine이고, Kotlineseo Listneun covariant-igi ttaemun입니다 (variance juje-eseo imi manjieobwat-eul geosimnida). Hajiman oneureun “covariance”ran dan-eo jachega jungkyohaejineun 않고, gyo-gwa-ga jungkyohaejimnida: hamssuga beom-yonghaejyeotgo, kodeuneun deo 덜 “끈적”해졌습니다.
Aep-eseo-ui jageun dan-gye: console chulryeok-eul wihan gongtong contract
Jigeum urineun jichul-eul chuga하고 chulryeokhaneun console aep을 gajigo itsseumnida. Choboja beojeon-ui list command는 daebudae ireon sik-imnida: command 안에서 julmunja formatting-eul han beon 하고, bogoseo에서도 또 하고, export에서도 또 하고… geureoda boni “gat-eun jichul”e daehae se gaji dareun format-i saenggipnida. Peuro그램-i eoneu sungan “Formatting: String-ui bok-su”cheoreom 변합니다.
Igeol piharyeomyeon, jageun geotbuteo, geurigo honesthage sijakhaebopsida: “sayongja에게 boyeojul su inneun modeun geot-eun jashin-eul han julmunjaro pyohyeonhal jul and다.”
Inteopeiseureul mandeureobopsida:
interface CliPrintable {
fun toCliLine(): String
}
Ije Expensega i geoseul silhyeonhamnida:
data class Expense(
val id: String,
val title: String,
val amount: Double,
) : CliPrintable {
override fun toCliLine(): String = "[$id] $title: $amount"
}
Geurigo main (ttoneun list command-ui hamssu)eseoneun “dae충” chulryeokhaneun 게 아니라, hangsang gateun 형식으로 chulryeokhamnida:
fun printAll(items: List<CliPrintable>) {
for (item in items) {
println(item.toCliLine())
}
}
Sayong yepje:
fun main() {
val expenses: List<CliPrintable> = listOf(
Expense("e1", "Coffee", 3.5),
Expense("e2", "Transit", 2.75),
)
printAll(expenses)
// [e1] Coffee: 3.5
// [e2] Transit: 2.75
}
Yeogiseo uri-ga han jungyohan il: “mueoseul chulryeokhalji”wa “eotteoke chulryeokhalji”reul bunrihaet습니다. “Architecture”ran mal-i keuge deul릴 수도 있지만, sasil-eun dan순한 disipline-imnida: format-eun han gos-e salgo, modeun kodeuga geugeol sayong합니다.
Daeum jageun dan-gye-ro, imi julmunjareul mandeuneun dae-ryo sokseongdeul-i itneun gyeongu-e default silhaeng-eul neoh-eul su its습니다. Ye-reul deureo, “title”reul gajin gaecheu-deul-e daehae:
interface HasTitle {
val title: String
fun titleLine(): String = "• $title"
}
Keullaeseuneun geunyang val titleman silhyeonhamyeon doego, titleLine()eun “gibon 제공”badeul su itsseumnida. Default metodeuneun jeongmal ireon neukkim-ieoya 합니다: “합리적인 기본 동작”, geurigo “imsi bangpyeon (hack)”이 아닙니다.
6. Inteopeiseu sayong si jaju natananeun silsu
Oryu 1: inteopeiseu sokseong-eul storage field라고 saenggakhagi.
Jaju issneun hondong: hakseang-i inteopeiseu 안의 val id: Stringreul bogo, inteopeiseuga eodienga munjayeol-eul “jigo itda”라고 ye상합니다. Hajiman Kotlineseo inteopeiseuneun jeopgeun (getter/setter)man gyujeonghago, jeojang-ina gyeseon-eun silhyeon-ui yeokhal-imnida. “inteopeiseu = yogu-sahang”, “keullaeseu = guche”reul gieokhamyeon, meori ap-eun geosi hwak jul-eo듭니다.
Oryu 2: overridereul 빼먹고 “감으로 구현”haryeo hagi.
Gakkeum keullaeseu 안에 val id: Stringreul sseodo overridereul an butigo, geu daeum compile error-ina “dareun geot-i silhyeondoetda”neun cheoreom 느끼며 danghwangha-gido 합니다. Kotlineseo overrideneun 형식이 아니라 의도 표기입니다: “na-neun i contractreul ihaenghanda.” Hab-gyeokhae jomyeon, cheoeumbuteo baro buchineun seupgwan-eul 드리세요. Seatbelt-cheoreom sayonghamyeon 됩니다.
Oryu 3: inteopeiseureul neomu neolbeuge mandeulgi (“hamssu 18-gae combain”).
EverythingManager gat-eun inteopeiseureul mandeulgo, printing, validation, storage, geu리고 “커피도 내려라”까지 담고 싶-eojil 때가 있습니다. Geureom gyeolguk ban쯤-ui silhyeon-eun bingan metodeureul sse거나 exception-eul 던져야 합니다. Joh-eun inteopeiseuneun daebudae 좁고 주제 중심입니다: contract 하나에 책임 하나.
Oryu 4: contract-e eomneun geot-e 의존haneun default metodeu sseugi.
Default silhaeng-eun inteopeiseuga 보장하는 geot-man-e 의존haeya 합니다: geu-ui sokseong-gwa metodeu. Default metodeu 안에서 “silhyeoni eotteon sumgyeojin fieldreul gajigo itgeol georago 기대”h거나 “부작용을 일으킨다”reul jeonjehamae, fragilehan dongjag-gwa ye상 chi mot-han gyeolgwa를 얻게 됩니다. Choego-ui test: “na-ga saeroun keullaeseu-eseo i inteopeiseureul silhyeonhal ttae, nam-ui ‘마음속’을 읽지 않고도 가능할까?”
Oryu 5: “inteopeiseu = contract”wa “sangsok = hierarchy”reul hon동hagi.
Inteopeiseuneun gaecheu-ui “gajok jokbo”reul na타낼 pilyo-ga 없습니다. Inteopeiseuneun “능력”eul na타냅니다. Ige inteopeiseu-ui himimnida: han keullaeseuga “jichul”imyeonseo, dong시에 “chulryeokhal jul 아는 것”, “idreul gajin 것”일 수 있습니다. Ige jongsanghago 오히려 bar람직합니다. Kodeu가 deo modularhaejimnida.
7. Jajeom munje
- Wae inteopeiseureul contract라고 부르며, keullaeseuga : SomeInterfacereul sseul ttae guchejeogeuro mueoseul “yak-sok”han geos-inga?
- Momchega eomneun inteopeiseu metodeuwa momchega inneun inteopeiseu metodeuneun eotteon jeom-i dareumyeo, wae default silhaeng-i pilyohan-ga?
- Wae inteopeiseu 안의 valeun “field”ga 아니며, ireon sokseongeul keullaeseu-eseo silhyeonhaneun gajang ju-yo han du 가지 bangbeop-eun mueos-inga?
- Wae hamssureul sseul ttae guchejeok keullaeseu (Expense)ga 아니라, inteopeiseu (CliPrintable)reul 받도록 하면 silmueseo yuyonghan-ga?
- Inteopeiseuga neomu “ttokttokhae-jyeotda/dukkkeowojyeotda”neun sinho-neun mueosimyeo, geureon inteopeiseureul silhyeonhaneun keullaeseudeul-eun bo통 eotteon il-eul gyeok-ge doeneun-ga?
GO TO FULL VERSION