iT邦幫忙

2022 iThome 鐵人賽

DAY 12
0
Software Development

Kotlin on the way系列 第 12

Day 12 OO 能吃嗎? 介面、抽象與釀酒 abstract design

  • 分享至 

  • xImage
  •  

The closer you look, the less you see.
Now you see me.

  • design of abstract
  • in Kotlin
    • interface
    • abstract class
  • summary

design of abstract

要描述抽象,難就難在他很抽象,在 Kotlin 裡面,程式碼面抽象有兩種作法 interface, abstract class,透過抽象的定義,可以使調用方依賴於抽象而非實體,可以輕鬆的替換、降低耦合,而且也不再受限於依賴的建構子,只要實作類別能完成介面定義的公開方法就行,不是要重複使用才做抽象設計,即使有多個類別有屬於自己的抽象也沒問題,但也不要為做而做,變成過度設計了

抽象設計著重在

  • 對外以及對內的公開程度
  • 職責的內聚性
  • 層級的行為

但一切先從簡單的開始看吧,interface 是最基本的一種程式抽象

像是電腦的鍵盤本身也是一種抽象,當我們打字時,會按下不同的字母,而螢幕上會出現我們按下的內容

interface Keyboard {
    fun input()
}
interface Screen {
    fun display()
}

這我們並不關心背後的原理,像是訊號傳遞、轉換、記憶體、電位變化等等,只透過介面操作,可以讓我們以最小的可見性達到需要的成果,不需知道必要以外的細節(解耦)

in Kotlin

interface

那換到真實的程式裡面呢?

interface UserRepository{
    fun getUserProfile():UserProfile
}

class MockRepo:UserRepository{
    override fun getUserProfile():UserProfile
}
class UserProfileImpl(
    api:Api,
    db:Room
):UserProfile {
    override fun getUserProfile():UserProfile
}

class useCase(
    userRepo:UserRepository
)

那反過來看,介面其實是一種接口,而為了被外部使用,介面不僅不實作方法,他所有的方法也都會是公開的

abstarct class

abstarct classinterface 最大的差異在於, abstartct class 可以持有屬性、以定義的方法和尚未定義的方法,可以提供沒有實現,或是不完整的實現

class Telsa:Car(){
    override fun main() {
        println("hohoho")
    }
    
}

abstract class Car {
    private val str = "toast"
    fun toast(){
        println(str)
        main()
    }
    abstract fun main()
}

Tesla().toast()
//toast
//hohoho

最大的一個特點在於,在抽象類別裡,可以定義方法去呼叫還沒被實現的方法

summary

不論是 interface 或是 abstract class 都可以為程式達到解耦的效果
interface : 定義未實現的公開方法接口
abstract class : 可定義未實現的接口、商業邏輯(以實現的)、 private property

抽象可以讓我們得以控制依賴圖的方向,類別實體不應依賴於他們不直接使用的東西

用酒譜學程式

今天來用釀紅酒學抽象吧
紅酒在大家的印象可能是好市多的酒櫃,一箱一箱的酒瓶,那紅酒瓶本身其實就是抽象

interface Wine{
    fun aroma()
    fun taste()
}

而實作的部分會交給 factory,把紅葡萄除梗、榨汁、浸皮、過濾、控溫、發酵、品檢、熟成,最後做成紅酒

class WineFactory(
    yeast:Yeast,
    grape:Grape,
    sugar:Sugar
):AbstarctWineFactory,WineSeller{
    private fun pressGrapeJuice()
    private fun ferment()
    private fun aged()
    override fun produceWine():Wine
}

然後紅酒可能會簡單的分成各產區我以前的品酒老師看到這還不把我殺了

class FranceWine:Wine{
    override fun aroma()
    override fun taste()
}
class ItalyWine:Wine {
    override fun aroma()
    override fun taste()
}

而每款酒的香味和口感,則各依照他們的實作而有所不同

English

  • design of abstract
  • in Kotlin
    • interface
    • abstract class
  • summary

design of abstract

It is hard to describe abstract, because itself is abstract, in Kotlin, there are two way to define abstract behaviorinterface, abstract class, by using abstract, the caller could relay on abstract instead of instance, can easily replace instance, decouple, and no longer restrict on constructure, as long as the class can implement the abstract method, on the other hands, abstract is not only for reuse, you can define abstract for a class with a good reason.

abstratc focus on

  • visibility for outside and inside
  • Cohesion of responsibility
  • layer behavior

Let's start from simple one, interface is the basic of abstract in programming

like keyboard itself is an abstract, when we are typing, we press on different alphabet, and the screen display those content

interface Keyboard {
    fun input()
}
interface Screen {
    fun display()
}

We don't care about the theory under it, by using operator defined in interface we can rely on minimum visibility to get what we need , without knowing too much detail (decouple)

in Kotlin

interface

What is it like in programming?

interface UserRepository{
    fun getUserProfile():UserProfile
}

class MockRepo:UserRepository{
    override fun getUserProfile():UserProfile
}
class UserProfileImpl(
    api:Api,
    db:Room
):UserProfile {
    override fun getUserProfile():UserProfile
}

class useCase(
    userRepo:UserRepository
)

interface is build for used, so it won;t implement method itself, and its methods will be open

abstarct class

The difference betweenabstract class and interface is abstract class can holding properties, define method and undefine method

class Telsa:Car(){
    override fun main() {
        println("hohoho")
    }
    
}

abstract class Car {
    private val str = "toast"
    fun toast(){
        println(str)
        main()
    }
    abstract fun main()
}

Tesla().toast()
//toast
//hohoho

Inside abstract class, you can define method to call undefined method

summary

Both interface and abstract class could decouple program

interface : provide undefined method
abstract class : provide undefined method、business(defined method)、 private property

Using abstract allow us to control direction of dependency graph, class instance shouldn't relay on things they won't use directorly


上一篇
Day 11 OO 能吃嗎? 繼承與調香技法 inheritance
下一篇
Day 13 OO 能吃嗎? 封裝
系列文
Kotlin on the way31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言