【问题标题】:How to declare a function with a concrete return type conforming to a protocol?如何声明具有符合协议的具体返回类型的函数?
【发布时间】:2015-04-27 09:15:59
【问题描述】:

编辑: 这个问题是在swift 添加some 关键字之前写的,已经过时了

在objective-c中我可以声明一个返回类型的方法:

-(UIView<MyProtocol> *)someMethod;

在本例中,该方法返回一个符合MyProtocol 协议的UIView

我想在 swift 中做类似的事情:

protocol MyProtocol {
  var someProperty : Int {get set}
}

protocol MyDelegate {
  func someMethod() -> UIView : MyProtocol // the view should conform to the protocol - I don't care what kind of view it is - I don't want to define a specific type of view
}

通常 - 委托应返回带有 var "someProperty" 的 UIView

不想想定义一个具体的UIView 类。 我希望用户能够返回任何类型的UIView(只要它符合协议)

我写的语法无效 - 我应该怎么写?

【问题讨论】:

  • 可能你可以用许多编程语言来做这样的事情。与 Objective-C 没有特定的关系。删除了标签。

标签: ios swift protocols generics


【解决方案1】:

你可以只使用协议作为类型:

protocol MyDelegate {
    func someMethod() -> MyProtocol
}

并像这样使用它:

protocol MyProtocol {
    var someProperty : Int {get set}
}

class CustomView: UIView, MyProtocol {
    var someProperty = 2
}

protocol MyDelegate {
    func someMethod() -> MyProtocol
}

struct Delegate: MyDelegate {
    func someMethod() -> MyProtocol {
        return CustomView()
    }
}

let delegate = Delegate()
let view = delegate.someMethod()
let property = view.someProperty // property = 2

【讨论】:

  • 第一个没有肯定回答这个问题。我试试第二个
  • 很公平,它缺少UIView 约束,但它可以保证协议一致性。
  • 不工作;得到一个错误:一行上的连续声明必须用';'分隔
  • 我有一些 Xcode 打嗝,所以它没有抛出错误,但我发现我错了。用唯一可行的例子更新了我的答案(我不确定你是怎么做到的)。
【解决方案2】:

这在 Swift 中是不可能的。并非 Obj-C 中的所有可能都必须在 Swift 中成为可能。创建类型要求时,您只能使用 protocol&lt;..., ...&gt; 语法组合协议,但不能组合类和协议。

从技术上讲,这应该有利于您的架构。您可能会找到一种解决方法,但我建议您不要这样做。避免将类与协议结合是有原因的,因为接口更难处理。大多数 OOP 语言没有这种语法。许多常用语言甚至没有组合协议的语法。

【讨论】:

  • 当然有。几乎所有语言都可以从一个超类继承并实现任意数量的接口(协议)。
  • 这是一个在所有 Objective-c 和 UIKit/Foundation 框架中都被广泛使用的模式。
  • @AvnerBarr 我不是在谈论继承,我是在谈论在传递参数、从方法返回等时指定类型要求。我知道这在 Obj-C 中是可能的(不经常使用但可能) .在大多数其他语言中这是不可能的,包括 Swift。
  • Uikit 定义了实现接口的返回类型 Uiview 的方法。这对于向层次结构添加视图非常有用,无需强加特定类型,但在对象上定义了方法和变量
  • @AvnerBarr 你能链接其中一个吗?我现在不记得有任何这样的方法。无论如何,我知道它可能很有用,但有更清洁的方法可以做到这一点。 Swift 只是没有这个特性,和大多数其他语言一样。
【解决方案3】:
protocol MyProtocol {
  var someProperty : Int {get set}
}

protocol MyDelegate {
  func someMethod<T: UIView & MyProtocol>() -> T // the view should conform to the protocol - I don't care what kind of view it is - I don't want to define a specific type of view
}

class MyDelegateTestView : UIView, MyProtocol {
    var someProperty: Int = 10
}

class MyDelegateTestClass : MyDelegate {
    func someMethod<T>() -> T where T : UIView, T : MyProtocol {
        return MyDelegateTestView() as! T
    }
}

【讨论】:

    【解决方案4】:

    问题是在swift-ui时代之前写的

    “some”关键字通过允许从函数返回不透明类型解决了这个问题

    protocol MyDelegate {
      func someMethod() -> some MyProtocol 
    }
    

    【讨论】:

      【解决方案5】:

      下面是一种方法。

      func myMethod(string: String) -> MyClass:MyProtocol? {
      
      }
      

      您可以使用没有可选类型的 MyClass: MyProtocol。

      【讨论】:

      • 得到同样的错误:一行上的连续声明必须用';'分隔
      猜你喜欢
      • 1970-01-01
      • 2019-03-04
      • 2019-11-23
      • 2015-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-02
      相关资源
      最近更新 更多