当前位置: 首页 > 面试题库 >

全局函数的Swift协议和返回类型

桓瀚
2023-03-14
问题内容

这是对问题的跟进:协议func返回Self。协议如下:

protocol Copyable {
    init(copy: Self)
    func copy() -> Self
}

以下工作正常,但copy()每个实现的功能完全相同,即

func copy() -> Self {
   return self.dynamicType(copy: self)
}

按照这个http://nshipster.com/swift-default-protocol-
implementations/
我尝试了一个全局功能

func copy<T : Copyable>(makeCopy: T) -> T {
    return makeCopy.dynamicType(copy: makeCopy)
}

但是,在实现以下协议的类中调用它时

protocol Mutatable : Copyable {
    func mutated() -> Self
}

class C : Mutatable {

    var a = 0

    required init(_ a: Int) {
        self.a = a
    }

    required init(copy: C) {
        a = copy.a
    }

    func mutated() -> Self {
        let mutated = copy(self)

        mutated.a++

        return mutated // error: 'C' is not convertible to 'Self'
    }

}

我得到指出的错误。当我键入mutated自动完成显示mutated(C),我不知道那是什么意思。我也尝试过添加requiredfuncmutated()但显然required只允许这样做inits。有什么办法可以使它正常工作吗?


问题答案:

这个问题的形式与副本一相同,解决方案也相同。将变异设为初始值设定项,而不是方法。

protocol Copyable {
  init(copy: Self)
}

protocol Mutatable : Copyable {
  init(byMutating: Self)
}

class C : Mutatable {
  var a = 0

  required init(_ a: Int) {
    self.a = a
  }

  required init(copy: C) {
    a = copy.a
  }

  required convenience init(byMutating: C) {
    self.init(copy: byMutating)
    self.a++
  }
}

// These are purely for convenience
func copy<T : Copyable>(x: T) -> T {
  return x.dynamicType(copy: x)
}

func mutated<T: Mutatable>(x: T) -> T {
  return x.dynamicType(byMutating: x)
}

但是要重申链接文章中Mattt的观点,您可以C(copy: x)非常方便地使用语法,并且可以copy(x)非常方便地使用语法,并且始终存在x.dynamicType(copy: x)。但是,如果x.copy()没有一些烦人的工作,就无法拥有语法。您要么必须func copy() -> Self { return copy(self) }在每个类中进行复制,要么必须创建一些实现此方法并C最终继承的具体类。目前,这是Swift的基本限制。我同意Mattt对可能解决方案的诊断,并怀疑将来可能会添加某种特征系统,可能与Scala相似。

值得关注Mattt的评论,“所有这些都凸显了Swift中方法和函数之间的巨大张力”。这是另一种说法,即面向对象的范式和功能的范式之间存在张力,在它们之间移动会造成一些脱节。语言试图用各种功能来解决这个问题,但是带有消息和属性的对象与带有数据和组合器的函数之间存在重要的区别,并且“充分利用两者”有时会产生一些粗糙的边缘。

将Swift与其他语言进行比较时,很容易忘记v0.9和v2.11之间存在很大差异。我们最喜欢的语言中许多我们认为理所当然的东西在其v1中也不存在。

就您的评论而言,您可能会认为mutated是类型Self。但这是类型C,如您的自动完成功能所示。和以前C一样,Self除非您可以保证没有子类(C不是要么final是struct),否则和之前一样。除非您使用,否则Swift类型是在编译时而不是运行时解析的dynamicType

更具体一点,Swift会看这一行:

    let mutated = copy(self)

它指出,它copy在其参数类型上是通用的,并且必须copy 在编译时 构造一个版本
进行调用。没有类型Self。它只是一个占位符,必须在编译时解决。self在此词汇范围内的类型是C。如此构造copy<C>。但是,如果您将其子类化C,则可能是错误的函数(在这种情况下,可能是错误的)。这与以下内容密切相关
:

类型autocomplete表示的事实(C)不是CSwift函数和元组如何工作的次要副作用,而且定期出现,但我还没有遇到真正重要的案例。类似的Swift函数func f(x: Int, y:Int)实际上没有两个参数。它具有一个类型为2的2元组参数(Int, Int)。这个事实对于currying语法的工作方式非常重要(有关Swift中的curring的更多信息,请参见Swift编程语言)。因此,当您进行专业化处理时copy,可以使用类型为1的元组对其进行专业化处理(C)。(或者,编译器可能只是尝试将其作为各种尝试之一,而这只是它报告的结果。)在Swift中,任何值都可以被琐碎地交换为相同类型的1元组。因此,的回报copy实际上是的1元组C,书面的(C)。我怀疑Swift编译器会随着时间的推移改进其消息以消除多余的括号,但这就是为什么它们有时会出现的原因。



 类似资料:
  • 本文向大家介绍Pythonround()函数平局和返回类型,包括了Pythonround()函数平局和返回类型的使用技巧和注意事项,需要的朋友参考一下 示例 round() 在Python 2中,使用round()相等接近两个整数的数字将返回距离0最远的数字。例如: Python 2.x 2.7 然而,在 Python 3中,round ()将返回偶数(即银行的四舍五入)。例如: Python 3

  • 问题内容: 该文件说: Swift编译器会自动将C和Objective-C源文件中定义的全局常量作为Swift全局常量导入。 但这并没有说相反的话。我需要定义一个全局swift常数,并且能够像全局c常数一样客观地看到它。如快速定义: 并在物镜c端使用它,例如 我该怎么办?我已经导入了迅速自动生成的标题,例如: 在Xcode中,如果我使用它,它将带我到swift代码中的正确位置,但是在编译时,我得到

  • 本文向大家介绍Swift传递和返回函数,包括了Swift传递和返回函数的使用技巧和注意事项,需要的朋友参考一下 示例 以下函数返回另一个函数作为其结果,可以稍后将其分配给变量并调用:            

  • 协议(Protocols)为方法,属性和其他需求功能提供了蓝图。 它为方法或属性骨架而不是实现。 通过定义类,函数和枚举,可以进一步完成方法和属性的实现。 协议的一致性满足了协议要求的方法或属性。 语法 协议也遵循与类,结构和枚举类似的语法 - 协议在类,结构或枚举类型名称之后声明。 单个和多个协议声明也是可以的。 如果定义了多个协议,则必须用逗号分隔。 当要为超类定义协议时,协议名称应使用逗号跟

  • 协议规定了用来实现某一特定功能所必需的方法和属性。 任意能够满足协议要求的类型被称为遵循(conform)这个协议。 类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能。 语法 协议的语法格式如下: protocol SomeProtocol { // 协议内容 } 要使类遵循某个协议,需要在类型名称后加上协议名称,中间以冒号:分隔,作为类型定义的一部分。遵循

  • 问题内容: 在Objective- C中,可以将符合协议的类指定为方法参数。例如,我可以有一个只允许符合的方法: 我找不到在Swift中执行此操作的方法(也许尚不可能)。您可以使用来指定多种协议,但是您又如何要求该对象属于特定类呢? 问题答案: 您可以将其定义为通用函数,并使用类型约束来同时要求类和协议。 斯威夫特4 Swift 3 (也适用于Swift 4) 迅捷2