簡體   English   中英

如何將方法的返回類型編寫為符合協議的 class + swift

[英]How to write a return type of a method as a class that conforms to a protocol + swift

我正在做一個項目,我需要使用 swift 在 iOS 中復制使用 android 開發的功能。

在 android 應用程序中,有一個地方提到了抽象 class設備中方法的返回類型,

abstract fun getDT(): Class<out DeviceType>

其中 DeviceType 本身就是另一個抽象 class。 所以我從android開發者那里聽說,在這個方法的實際實現中,它會返回一個繼承DeviceType的class,如下所示,

override fun getDT(): Class<out DeviceType> {
    return type1DeviceType::class.java
}

其中 type1DeviceType 實際上繼承了 DeviceType 抽象 class 如下

public class type1DeviceType extends DeviceType {

所以在我們的 iOS 術語中,抽象 class 的等價物是協議。

所以在 iOS 中,我編寫了一個協議來代替 Android 中的抽象 class。 而對於其中抽象function的返回類型,我需要提到返回類型是符合DeviceType協議的東西。 知道如何實現這一目標嗎?

我在 swift 中嘗試了以下代碼。

 public func getDT() -> DeviceTypeProtocol.Type {
    return type1DeviceType as! DeviceTypeProtocol.Type
}

但是在運行時,我得到了錯誤,

Swift 運行時失敗:類型轉換失敗

你的意思是這樣的嗎?

protocol DeviceType {
    func getDeviceType() -> DeviceType.Type
}

extension DeviceType {
    func getDeviceType() -> DeviceType.Type { Self.self }
}



class AudioDevice: DeviceType {
    func getDeviceType() -> DeviceType.Type { AudioDevice.self }
}

class Microphone: AudioDevice {
}

class Speaker: AudioDevice {
    override func getDeviceType() -> DeviceType.Type { Speaker.self }
}



class VideoDevice: DeviceType {}

class Camera: VideoDevice {}

class Monitor: VideoDevice {
    func getDeviceType() -> DeviceType.Type { VideoDevice.self }
}


func test() {
    print(AudioDevice().getDeviceType()) // prints AudioDevice
    print(Microphone().getDeviceType()) // prints AudioDevice
    print(Speaker().getDeviceType()) // prints Speaker
    print(VideoDevice().getDeviceType()) // prints VideoDevice
    print(Camera().getDeviceType()) // prints Camera
    print(Monitor().getDeviceType()) // prints VideoDevice
}

DeviceType定義了一個協議,該協議具有返回帶有getDeviceType的類型的能力,該類型也是DeviceType的類型。

您所描述的內容不需要擴展協議,但我想以任何一種方式進行演示。 它用於VideoDevice

所以AudioDevice繼承了協議,並顯式定義了獲取設備類型的方法。 因為它返回的是它打印出來的AudioDevice類型。 Microphone繼承自AudioDevice (不是來自DeviceType )並且不覆蓋該方法,因此它也返回AudioDevice 並且Speaker也繼承自AudioDevice但確實覆蓋了該方法,因此返回Speaker

VideoDevice更有趣一些。 它繼承了協議,但沒有明確定義所需的方法。 因此它使用具有Self.self有趣語法的擴展。 它基本上只是意味着“返回動態自我的 static 類型的任何東西”如果這更有意義的話......這只是可能的,因為定義了協議的擴展。 刪除擴展將創建一個編譯時錯誤,讓您知道您確實需要定義該方法。 現在因為很好地定義了擴展,所以VideoDevice已經自己打印出來了。 VideoDevice (而不是DeviceType )繼承的Camera也是如此。 然后Monitor再次覆蓋該方法並打印出VideoDevice而不是Monitor

當然,您可以將設備類別(在本例中為視頻和音頻)定義為繼承設備類型的協議。 您還可以對這些協議進行擴展。 看看這個例子:

protocol DeviceType {
    func getDeviceType() -> DeviceType.Type
}


protocol AudioDevice: DeviceType { }

class Microphone: AudioDevice {
    func getDeviceType() -> DeviceType.Type { Microphone.self }
}

class Speaker: AudioDevice {
    func getDeviceType() -> DeviceType.Type { Speaker.self }
}


protocol VideoDevice: DeviceType { }

extension VideoDevice {
    func getDeviceType() -> DeviceType.Type { Self.self }
}

class Camera: VideoDevice {
}
class Monitor: VideoDevice {
    func getDeviceType() -> DeviceType.Type { Camera.self }
}


func test() {
    print(Microphone().getDeviceType()) // prints Microphone
    print(Speaker().getDeviceType()) // prints Speaker
    print(Camera().getDeviceType()) // prints Camera
    print(Monitor().getDeviceType()) // prints Camera
}

那么 Swift 協議與 Kotlin 抽象 class 不同。 更接近的比較是 Kotlin接口和 Swift 協議

我對你的要求在這里有點困惑。 但是,根據我在這里看到的情況,這似乎是面向協議編程的一個很好的案例,它可以減少對多個嵌套抽象類或子類的需求。

我也有點困惑,為什么您需要獲取 DeviceType 的DeviceType .... DeviceType本身不是DeviceType嗎?

在我看來,這樣的事情似乎要簡單得多:

Kotlin

Kotlin 操場

interface Device {
    fun doSomething()
}

interface MobileDevice: Device {
    fun onTap()
}

interface DesktopDevice: Device {
    fun onClick()
}

interface WearableDevice: Device {
    fun onButtonPush()
}

class AndroidPhone: MobileDevice {
    override fun doSomething() {
        println("I'm an Android phone.")
    }
    
    override fun onTap() {
        println("Tap the screen.")
    }
}

class MacDesktop: DesktopDevice {
    override fun doSomething() {
        println("I'm a Mac desktop.")
    }
    
    override fun onClick() {
        println("Click the magic mouse.")
    }
}

class SmartNecklace: WearableDevice {
    override fun doSomething() {
        println("I'm a smart necklace.")
    }
    
    override fun onButtonPush() {
        println("Help! I've fallen and I can't get up!")
    }
}

可以這樣使用:

fun exampleFunction() {
    val mobile = AndroidPhone()
    val desktop = MacDesktop()
    val wearable = SmartNecklace()
    mobile.doSomething()
    desktop.doSomething()
    wearable.doSomething()
    
    val devices = listOf(mobile, desktop, wearable)
    
    devices.forEach { device ->
        when (device) {
            is MobileDevice -> device.onTap()
            is DesktopDevice -> device.onClick()
            is WearableDevice -> device.onButtonPush()
            else -> println("Unknown Type.")
        }
    }
}

Swift

在您的 Swift 版本中,您還可以 向協議添加一些默認行為(請參閱下面的協議擴展示例)。

protocol Device {
    func doSomething()
}

protocol MobileDevice: Device {
    func onTap()
}

protocol DesktopDevice: Device {
    func onClick()
}

protocol WearableDevice: Device {
    func onButtonPush()
}

extension Device {
    func doSomething() {
        print("Doing default thing.")
    }
}

extension WearableDevice {
    func onButtonPush() {
        print("Help! I've defaulted and I can't get up!")
    }
}

class AndroidPhone: MobileDevice {
    func onTap() {
        print("Tap the screen.")
    }
}

class MacDesktop: DesktopDevice {
    func doSomething() {
        print("I'm a Mac desktop.")
    }

    func onClick() {
        print("Click the magic mouse.")
    }
}

class SmartNecklace: WearableDevice {
    func doSomething() {
        print("I'm a smart necklace.")
    }
}

可以這樣使用:

func exampleFunction() {
    let mobile = AndroidPhone()
    let desktop = MacDesktop()
    let wearable = SmartNecklace()

    mobile.doSomething()
    desktop.doSomething()
    wearable.doSomething()

    let devices: Array<Device> = [mobile, desktop, wearable]

    devices.forEach { device in
        switch (device) {
        case let device as MobileDevice:
            device.onTap()
        case let device as DesktopDevice:
            device.onClick()
        case let device as WearableDevice:
            device.onButtonPush()
        default:
            print("Uknown type")
        }
    }
}

Output

Doing default thing.
I'm a Mac desktop.
I'm a smart necklace.
Tap the screen.
Click the magic mouse.
Help! I've defaulted and I can't get up!

如果你做了這樣的事情,你就已經知道 object 的類型(如 switch/when 塊所示)。 您不需要獲取設備類型的方法。 你會得到它。

如果您的問題有什么我遺漏的,請告訴我。

至於你的錯誤:

Swift runtime failure: type cast failed

如果演員表失敗,我猜type1DeviceTypeDeviceTypeProtocol ,而不是DeviceTypeProtocol.Type

public func getDT() -> DeviceTypeProtocol.Type {
    return type1DeviceType as! DeviceTypeProtocol
}

檢查當您嘗試輸入或使用 type1DeviceType 時顯示的類型,或查看其快速幫助以查看類型。 當你到達那一點時,你認為實際的類型是什么?

我還要問,以與 Android 版本完全相同的方式執行此操作有多重要? 我總是建議正確規划跨平台,以使事情盡可能相似。 它總是有幫助的,尤其是在作為一個團隊一起調試和構建事物時。

從上面的代碼可以看出,它幾乎是准確的。 這也是我做事的方式。 但不以能夠完成工作為代價。

class type1DeviceType: DeviceTypeProtocol {
  public func getDT() -> DeviceTypeProtocol.Type {
    // return type1DeviceType as! DeviceTypeProtocol.Type
    return type1DeviceType.self
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM