swift - 如何在 Swift 中使用具有关联类型的协议(protocol)作为返回值?

标签 swift generics

我正在尝试使用具有关联类型的协议(protocol)作为类函数的返回值。

Another post stackoverflow 上的这里是关于同一个问题,根据这篇文章的回答,我尝试了以下操作:

// addArg takes a single Int argument and returns something, 
// which is capable of adding a another Int argument
class OpWithNoArg {
    func addArg<OP: OpWithOneArg where OP.ArgType == Int>(arg: Int) -> OP {
        return OpWithOneArgImpl() // (1) error here !
    }
}

// a protocol with associated type, which allows adding another
// argument of a not yet specified type
protocol OpWithOneArg {
    typealias ArgType
    func addAnotherArg(arg: ArgType)
}

// an implementation of the protocol above, 
// which fixes the associated type to an Int
class OpWithOneArgImpl : OpWithOneArg {
    typealias ArgType = Int
    func addAnotherArg(arg: Int) {
        // ...
    }
}

Xcode 7.0 Beta 4 中标有(1)的行的错误是

cannot convert return expression of type 'OpWithOneArgImpl' to expected return type 'OP'

如果我将返回值更改为可选值并返回 nil,则示例编译成功:

// return null  
class OpWithNoArg {
    func addArg<OP: OpWithOneArg where OP.ArgType == Int>(arg: Int) -> OP? {
        // return OpWithOneArgImpl()
        return nil
    }
}

这种使用关联类型作为返回值的协议(protocol)的方式在swift中是否可行,如果是这样,如何解决上述编译器错误?

提前致谢!

编辑:

在 Java 中,代码类似于以下片段。我试图在 Swift 中找到一种方法来实现相同的目标。

class C {
    <T> P<T> f(T arg) {
        return new PImpl();
    }
}

interface P<S> {
    void g(S arg);
}

class PImpl<S> implements P<S> {
    PImpl() {}
    public void g(S arg) {}
}

最佳答案

不清楚您要实现的目标,但恕我直言,错误源于这样一个事实:在您的 addArg 函数中,您定义了一个通常应该使用的通用类型 OP在函数的参数和主体中。

相反,您返回一个非通用类型,试图强制将其视为通用 `OP。

快速修复可能是强制转换为返回对象的 OP:

return OpWithOneArgImpl() as !OP

但我不推荐它。

在您的示例中,您的 addArg 将始终返回一个 OpWithOneArgImpl,因此它可以被定义为一个 func addArg(arg: I​​nt) -> OpWithOneArgImpl

希望这对您有所帮助。

编辑:

可能这不是您要实现的目标,但希望它能有所帮助 更清楚地解释我上面的意图。

protocol OpWithOneArg {
    typealias ArgType
    func addAnotherArg(arg: ArgType)
    init() // Must have a init with no argument
}


class OpWithOneArgImpl : OpWithOneArg {
    typealias ArgType = Int
    func addAnotherArg(arg: Int) {
        // ...
    }
    required init() {
        // init implementation
    }
}

class OpWithNoArg {
    func addArgWithOPType<OP: OpWithOneArg where OP.ArgType == Int>(op: OP.Type, arg: Int) -> OP {
        return OP() // Here we use the init
    }
}

let foo = OpWithNoArg()
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: 3)

编辑:

也许您可以研究泛型类型的使用:

protocol OpWithOneArg {
    typealias ArgType
    func addAnotherArg(arg: ArgType)
    init() // Must have a init with no argument
}


class OpWithOneArgImpl<T> : OpWithOneArg { // Generic implementation confirming to protocol
    typealias ArgType = T
    func addAnotherArg(arg: T) {
        // ...
    }
    required init() {
        // init implementation
    }
}


class OpWithNoArg {
    func addArgWithOPType<OP: OpWithOneArg>(op: OP.Type, arg: OP.ArgType) -> OP {
        return OP() // Here we use the init
    }
}

let foo = OpWithNoArg()

// OpWithOneArgImpl<Int>
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: 3) 

// OpWithOneArgImpl<String>
foo.addArgWithOPType(OpWithOneArgImpl.self, arg: "Hello")

关于swift - 如何在 Swift 中使用具有关联类型的协议(protocol)作为返回值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31896059/

相关文章:

ios - Swift 连续旋转动画不是那么连续

ios - 如何在 iOS Swift 中设置特定索引的 Collection View 单元格?

.net - IDisposable : Method 'X' has multiple definitions with identical signatures

c# - 根据通用接口(interface)获取类属性

Java:尝试使用错误类型作为映射键时出现编译器或 Eclipse 警告

ios - Typhoon:从程序集中检索 Storyboard时出现异常

swift - 我正在按照刚刚为 Swift 发布的 CS193p 讲座创建一个计算器应用程序。如何将 Pi 实现为操作数 & 和运算?

ios - 如何根据我的json中的bool值过滤和显示 TableView 和 Collection View 值

C# - 我们应该如何在接口(interface)中实现 default(T)?

delphi - 使用泛型类型数组的类成员调整类实例大小