【问题标题】:Error claims a protocol is a generic type, but no generics are used错误声称协议是泛型类型,但没有使用泛型
【发布时间】:2018-02-15 10:08:50
【问题描述】:

我希望实现类似于Notification.Name 的模式,任何人都可以稍后通过extension 添加一个模式,如下所示:

斯威夫特 4

public protocol Foo {
    var bar: String { get }
}



public struct FooImpl: Foo {
    public let bar: String
}



public extension Foo {
    public static let baz: Foo = FooImpl(bar: "baz")
}

// Ideal usage:
someFuncThatTakesAFoo(.baz)

这对我来说似乎很好,但是在编译时我遇到了一个令人困惑的错误:

/path/to/main.swift:24:23: error: static stored properties not supported in generic types
    public static let baz: Foo = FooImpl(bar: "baz")
           ~~~~~~     ^

这是怎么回事,有什么解决办法?

【问题讨论】:

标签: swift generics compiler-errors swift-extensions


【解决方案1】:

这是一条奇怪的错误消息,但您的代码无论如何都不应该编译。扩展中不支持存储的属性,因此会出现错误。

通过删除 static 关键字并将 baz 保留为存储属性,您会得到一个有意义的错误:

扩展可能不包含存储的属性

将声明更改为计算属性(并因此将其声明为可变)错误会神奇地消失。

public protocol Foo {
    var bar: String { get }
}

public struct FooImpl: Foo {
    public let bar: String
}


public extension Foo {
    public static var baz: Foo {
        return FooImpl(bar: "baz")
    }
}

【讨论】:

  • 但这很好用:extension FooImpl { static let baz = FooImpl(bar: "baz") }。就像我说的,这是 Swift 中的一种常见做法,尤其是在 Notification.Name 中使用,以允许语义创建和使用点前缀语法的对象实例
  • 另外,当我尝试使用像let x = Foo.baz 这样的解决方案时,我得到一个新的令人困惑的错误:Static member 'baz' cannot be used on protocol metatype 'Foo.Protocol'
  • Here 你实际上可以尝试运行代码,它编译没有问题。另请查看this 答案,该答案还说明您不能在协议扩展中存储属性。而且,您评论中的示例与问题中的示例不同,评论一是结构扩展,而问题一是协议扩展。
  • 好吧,那应该行不通。协议本身并不存在。 let x = FooImpl.baz 有效,let Foo.baz 无效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-09
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多