【问题标题】:Method Naming Issues Swift方法命名问题 Swift
【发布时间】:2014-07-31 08:49:19
【问题描述】:

我希望创建一个等效于

的 Swift 方法
+ (void)insertFileWithService:(GTLServiceDrive *)service
                    title:(NSString *)title

当我输入时

func insertFileWithService(service: GTLServiceDrive,
    title title: String,

我得到一个警告标题标题可以更简洁地表达为#title

但是当我把它改成 func insertFileWithService(服务:GTLServiceDrive, #title: 字符串

我收到警告,参数标题中的“#”已经是关键字参数名称

我是否应该忽略这些警告并将其归咎于 Beta 版中的错误?

【问题讨论】:

  • 如果你这样做:func insertFileWithService(service: GTLServiceDrive, #title: String) 你会收到警告吗?
  • 是函数还是方法?见stackoverflow.com/a/24046893/390581——它们的行为不同。
  • 是的,如果函数是类成员而不是全局成员,我可以重现这一点。 Ryan,您可能想扩展您的问题以显示一个最低限度的完整示例。但我会说这是一个 Xcode 错误。
  • @MattGibson,因为他可以删除#(按照比尔的建议),对吧?
  • Jean-Philippe 这是一种方法 - 我已经更新了我的问题,谢谢

标签: swift


【解决方案1】:

我不认为这是一个错误,事实上,这就是该语言的设计方式:


来自 Apple 的东西 (https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html#//apple_ref/doc/uid/TP40014097-CH15-XID_300):

class Counter {
    var count: Int = 0
    func incrementBy(amount: Int, numberOfTimes: Int) {
        count += amount * numberOfTimes
    }
}

这个 incrementBy 方法有两个参数——amount 和 numberOfTimes。默认情况下,Swift 仅将 amount 视为本地名称,但将 numberOfTimes 视为本地名称和外部名称。你调用方法如下:

let counter = Counter()
counter.incrementBy(5, numberOfTimes: 3)
// counter value is now 15

你不需要为第一个参数值定义一个外部参数名,因为它的目的从函数名 incrementBy 就很清楚了。但是,第二个参数由外部参数名称限定,以便在调用方法时明确其用途。

此默认行为有效地将方法视为您在 numberOfTimes 参数之前写了一个井号 (#)


基本上,对于类中的方法,第一个参数默认为仅内部参数名称。所有后续参数名称默认为外部名称,其中外部名称默认为参数名称。因此,# 是多余的。

func insertFileWithService(service: GTLServiceDrive, title: String)

相当于

func insertFileWithService(service: GTLServiceDrive, #title: String)

对于方法,而不是函数。这就是您收到警告的原因。

【讨论】:

  • 我在《如果要为函数参数提供外部参数名称,并且本地参数名称已经是合适的名称可以使用,则无需编写相同为该参数命名两次。相反,只写一次名称,并在名称前加上井号 (#)。这告诉 Swift 使用该名称作为本地参数名称和外部参数名称。”摘自:Apple Inc.“Swift 编程语言”。电子书。 itunes.apple.com/il/book/swift-programming-language/…
  • 如果我理解正确的话,这是否仅适用于函数而不适用于方法
  • 正确,您的报价是针对功能而不是针对方法的。对于方法,本地参数名称假定为除第一个参数之外的所有参数的外部参数名称。请参阅我的帖子中引用的文字。对于方法,第二个参数的 # 是隐含的,这就是您收到警告的原因,添加 # 是不必要的,编译器希望您确定您知道您要完成的工作。
  • 谢谢你的完整解释。
【解决方案2】:

去掉井号,只用“title: String”

【讨论】:

  • 不,不会。 "title title: String" 与 "title: String" 完全相同。
【解决方案3】:

Swift 允许您在函数内部和外部以不同的方式命名参数。

当您希望参数在函数中具有不同的名称时,您可以使用这些“外部参数名称”。来自the book

有时在调用函数时命名每个参数很有用,以指示传递给函数的每个参数的用途 函数。

如果您希望函数的用户在调用您的函数时提供参数名称,请为每个函数定义一个外部参数名称 参数,除了本地参数名称。

由于您在内部和外部都使用相同的名称“title”,因此您可以按照 Swift 的建议跳过外部参数名称,并使用 # 前缀来表示内部引用的具有相同名称的命名外部参数.

书中的例子:

func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
    for character in string {
        if character == characterToFind {
            return true
        }
    }
    return false
}

【讨论】:

  • 这个例子会给出错误,“Extraneous '#' in parameter: 'characterToFind' 已经是关键字参数名称”。
【解决方案4】:

这样命名你的方法:

@objc(insertFileWithService:title:)
func insertFile(service: GTLServiceDrive, title: String)

然后从 Swift 中,这样称呼它:

obj.insertFile(serviceDrive, title: "Title")

在目标 C 中:

[obj insertFileWithService:serviceDrive title: @"Title"];

【讨论】:

  • 为什么@objc 注释在这里?只需注释类 (@objc class ...)。
  • @Jean-PhilippePellet 注解是为了给它一个更加Objective C友好的名字,而不会让Swift名字变得尴尬。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-17
  • 2015-08-26
相关资源
最近更新 更多