Well a Swift protocol is not the same as a Kotlin abstract class. A closer comparison would be Kotlin interface and Swift protocol.
I'm a little confused on what your requirements are here. However, based on what I see here it seems like a good case for Protocol Oriented Programming, which can mitigate the need for multiple nested abstract classes or subclasses.
I'm also a little confused why you would need to get the DeviceType of a DeviceType.... is the DeviceType itself not the DeviceType?
In my head it seems something like this would be a lot more simple:
Kotlin
See in Kotlin playground
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!")
}
}
Which could be used like:
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
In your Swift version you can also add some default behaviors to the protocols (see the protocol extension examples below).
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.")
}
}
Which could be used like:
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!
If you did something like this, you would already know the type by nature of the object (as seen in switch/when blocks). You wouldn't need a method to get the device type. You would just have it.
If there is something I'm missing from your question, let me know.
As for your error:
Swift runtime failure: type cast failed
If the cast is failing, I'm guessing type1DeviceType is a DeviceTypeProtocol, not a DeviceTypeProtocol.Type.
public func getDT() -> DeviceTypeProtocol.Type {
return type1DeviceType as! DeviceTypeProtocol
}
Check what the type shows up as when you try to type out or use type1DeviceType, or check the quick help on it to see the type. What do you see as the actual type when you get to that point?
I would also ask how important is it to do this the exact same way as the Android version? I always recommend proper planning cross-platform to keep things as similar as possible. It always helps, especially when debugging and building things together as a team.
And as you can see from the above code, it can be almost exact. That's how I do things as well. But not at the expense of being able to get the job done.