简体   繁体   English

在 Swift 中解开两种类型中的一种

[英]Unwrapping either one of two types in Swift

I have a method which does exactly the same thing for two types of data in Swift.我有一个方法可以对 Swift 中的两种类型的数据做完全相同的事情。

To keep things simple (and without duplicating a method) I pass AnyObject as an argument to my method which can be either of these two types.为了简单AnyObject (并且不复制方法),我将AnyObject作为参数传递给我的方法,该方法可以是这两种类型中的任何一种。 How to I unwrap it with an ||如何用||打开它(OR) statement so I can proceed? (OR) 语句以便我可以继续? Or maybe this done otherwise?或者也许这是以其他方式完成的?

func myFunc(data:AnyObject) {

    if let data = data as? TypeOne {
        // This works fine. But I need it to look something like unwrapping below
    }

    if let data = data as? TypeOne || let data = data as? TypeTwo { // <-- I need something like this
        // Do my stuff here, but this doesn't work
    }

}

I'm sure this is trivial in Swift, I just can't figure out how to make it work.我确信这在 Swift 中是微不足道的,我只是不知道如何让它工作。

You can't unify two different casts of the same thing.您无法将同一事物的两个不同类型统一起来。 You have to keep them separate because they are two different casts to two different types which the compiler needs to treat in two different ways.您必须将它们分开,因为它们是两种不同类型的两种不同类型,编译器需要以两种不同的方式处理它们。

var x = "howdy" as AnyObject
// x = 1 as AnyObject

// so x could have an underlying String or Int
switch x {
case let x as String:
    print(x)
case let x as Int:
    print(x)
default: break
}

You can call the same method from within those two different cases, if you have a way of passing a String or an Int to it;如果您有办法将 String 或 Int 传递给它,您可以在这两种不同的情况下调用相同的方法; but that's the best you can do.但这是你能做的最好的事情。

func printAnything(what:Any) {
    print(what)
}
switch x {
case let x as String:
    printAnything(x)
case let x as Int:
    printAnything(x)
default: break
}

Of course you can ask当然你可以问

if (x is String || x is Int) {

but the problem is that you are no closer to performing an actual cast .但问题是你离执行实际演员不近。 The casts will still have to be performed separately.演员表仍然必须单独进行。

Building on Clashsoft's comment, I think a protocol is the way to go here.基于 Clashsoft 的评论,我认为协议是实现这一目标的方法。 Rather than pass in AnyObject and unwrap, you can represent the needed functionality in a protocol to which both types conform.您可以在两种类型都符合的协议中表示所需的功能,而不是传入 AnyObject 并展开。

This ought to make the code easier to maintain, since you're coding toward specific behaviors rather then specific classes.这应该使代码更易于维护,因为您正在针对特定行为而不是特定类进行编码。

I mocked up some code in a playground that shows how this would work.我在操场上模拟了一些代码来展示这是如何工作的。

Hopefully it will be of some help!希望它会有所帮助!

protocol ObjectBehavior {
    var nickname: String { get set }
}

class TypeOne: ObjectBehavior {
    var nickname = "Type One"
}

class TypeTwo: ObjectBehavior {
    var nickname = "Type Two"
}

func myFunc(data: ObjectBehavior) -> String {
    return data.nickname
}

let object1 = TypeOne()
let object2 = TypeTwo()

println(myFunc(object1))
println(myFunc(object2))

Find if that shared code is exactly the same for both types.查找这两种类型的共享代码是否完全相同。 If yes:如果是:

protocol TypeOneOrTypeTwo {}

extension TypeOneOrTypeTwo {

    func thatSharedCode() {

        print("Hello, I am instance of \(self.dynamicType).")
    }
}

extension TypeOne: TypeOneOrTypeTwo {}
extension TypeTwo: TypeOneOrTypeTwo {}

If not:如果不:

protocol TypeOneOrTypeTwo {

    func thatSharedMethod()
}

extension TypeOne: TypeOneOrTypeTwo {

    func thatSharedMethod() {

        // code here:
    } 
}

extension TypeTwo: TypeOneOrTypeTwo {

    func thatSharedMethod() {

        // code here:
    } 
}

And here you go:你去吧:

func myFunc(data: AnyObject) {

    if let data = data as? TypeOneOrTypeTwo {

        data.thatSharedCode() // Or `thatSharedMethod()` if your implementation differs for types.
    }
}

You mean like this?你的意思是这样?

enum IntOrString {
    case int(value: Int)
    case string(value: String)
}

func parseInt(_ str: String) -> IntOrString {
    if let intValue = Int(str) {
        return IntOrString.int(value: intValue)
    }
    return IntOrString.string(value: str)
}

switch parseInt("123") {
case .int(let value):
    print("int value \(value)")
case .string(let value):
    print("string value \(value)")
}

switch parseInt("abc") {
case .int(let value):
    print("int value \(value)")
case .string(let value):
    print("string value \(value)")
}

output:输出:

int value 123
string value abc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM