【问题标题】:Cannot convert value of type NSNumber to expected argument type NSNumber无法将 NSNumber 类型的值转换为预期的参数类型 NSNumber
【发布时间】:2018-07-19 15:56:51
【问题描述】:

我在尝试使用从基类继承的泛型函数的参数时收到标题错误

基类:

BaseBottomBar: UIView {
    ...
    func formatDetailText<T>(value: T...) {
        assertionFailure("You shouldn't be using this base class")
    }
}

儿童班:

NewTicketBottomBar: BaseBottomBar {

    override func formatDetailText<NSNumber>(value: NSNumber...) {
        let priceAsCurrencyString = NumberFormatter.currencyFormatter.string(from: value[1]) //Error on this line
        assert(priceAsCurrencyString != nil, "The price cannot be nil")
        let newTicketText = String(format: "%4.0f", value[0]) + " / TOTAL : " + priceAsCurrencyString!
        detailLabel.text = newTicketText
    }
}

我想我的基本方法原型在某种程度上是错误的,但我看不出是怎么回事。

一开始我没有使用泛型方法,原型如下:

func formatDetailText(value: Double...) {
    ...
    let priceAsCurrencyString = NumberFormatter.currencyFormatter.string(from: NSNumber(value: value[1]))
    ...
}

这很好用

任何帮助将不胜感激

【问题讨论】:

  • 如果你想让它通用,你应该使用浮点协议的 Numeric、BinaryInteger。如果您需要使用 NSNumber,则无需将其设为通用。 func formatDetailText(value: NSNumber)
  • 感谢您的回答!我认为我需要它,因为此方法旨在在子类中被覆盖,但底部栏有时会显示文本而不是数字,这就是为什么在我的情况下数字协议不起作用

标签: swift generic-programming


【解决方案1】:

你似乎认为

override func formatDetailText<NSNumber>(value: NSNumber...) {

将重写方法中的通用&lt;T&gt; 解析为NSNumber。它没有。它只是为泛型引入了不同的名称;这里的 NSNumber 不是 NSNumber 类,它只是另一个通用的占位符名称,与 T 完全一样(实际上,它 T 的另一个名称)。

所以很自然,当你尝试在 NumberFormatter 的 string(from:) 中使用 NSNumber 的这个占位符时,编译器转身说:“伙计 [编译器来自加利福尼亚,它是这样说话的],我没有有理由认为您的占位符“NSNumber”实际上是 NSNumber。”

你需要给它一个这样想的理由。你的意思可能是

override func formatDetailText<T>(value: T...) where T : NSNumber {

【讨论】:

  • 感谢您的回答!我为 NSNumber 工作,并且我对 swift 编译器的工作原理有了更好的理解:) 如果可以的话,我希望它采用 StringDouble 类型的参数,但它们是结构而不是类有没有办法这样做?
  • 或者如果我想要一个字符串和 NSNumber 在数字的情况下,我应该让泛型类型从 NSString 继承吗?
  • 整个用例在我看来并不适合泛型。但这无关紧要。我回答了编译器问题。你想要做什么以及如何去做是一个完全不同的问题。
  • 感谢@matt,基本上我的 UI 中有一个底栏,需要显示有关应用程序当前状态的信息,例如价格或字符串。由于栏的设计永远不会改变,我希望能够重用相同的视图类并覆盖显示信息的方法。我面临的问题是,有时您有数字,而其他人则只有文字。所以在我的意义上,我需要创建一个泛型,以便能够传递我想要的任何参数,并将显示信息的责任留给视图类。
  • 我不明白为什么。对我来说,这听起来像是两个方法重载。就像apeth.com/swiftBook/ch02.html#_overloading 一个版本需要一个字符串,一个版本需要一个数字,完成。简单而简短。没有泛型,没有子类,什么都没有。但是,正如我所说,这种讨论是不恰当的。如果您想讨论您应该做的事情,请提出一个新问题。
【解决方案2】:

问题在于您的代码没有说参数必须是NSNumber。就是说它需要一个泛型类型,你想调用NSNumber,就像你在上面使用T一样。

错误消息是因为编译器无法保证名为NSNumber 的泛型类型是真正的NSNumber 实例。你可以向它传递一个字符串,让它知道它所知道的一切。

您的覆盖应该如下所示

override func formatDetailText<T: NSNumber>(value: T...)

【讨论】:

  • 感谢您的回答,归结为@matt 以不同语义提供的相同答案 :) 我也赞成您的回答,因为它回答了我的问题 :)
猜你喜欢
  • 1970-01-01
  • 2016-01-22
  • 2017-10-30
  • 2017-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多