从基类或协议继承静态字段 - 如何实现?

4

我希望能够拥有具有静态属性(字段)的类,该属性可以是从基类继承或从协议“混合”得出。并且每个类都应该有自己对该属性的实现。这种需求可行吗?最好是不可变的。

class C1 {
  static let stProperty = "my prorepty1"
}

class C2 {
  static let stProperty = "my prorepty2"
}

1
你对这个具体的使用案例是什么? - Stefan Arentz
3个回答

2

你可以通过协议来实现这一点:

protocol SomeProtocol {
    static var foo: String { get }
}

class One: SomeProtocol {
    class var foo: String {
        get {
            return "This is One"
        }
    }
}

顺便说一句,我同意下面Rob Napier的看法,这个功能有点奇怪。我认为可能有用例,但我也认为可以使用其他语言功能更好地实现它们


也许将 SomeProtocol 转换为类会更好? - Incerteza
这取决于您要解决的问题。在许多情况下,继承是错误的解决方案。问题在于所有事物是否基本上都是“某种X的一种形式”(在这种情况下,继承是好的),还是它们只是“执行类似X的任务”(在这种情况下,协议是正确的答案)。如果有疑问,请使用协议。 - Rob Napier

2

这是可能的,但在Swift中要使其有用确实很困难。你打算如何引用该属性?我们从一个超级简单的实现开始:

protocol SomeProtocol {
    static var prop: String { get }
}

class C1: SomeProtocol {
    static let prop = "This is One"
}

太好了。现在我需要一个使用此功能的函数:
func useProp(x: SomeProtocol) -> String {
    return x.prop
    // 'SomeProtocol' does not have a member named 'prop'
}

那不起作用。 x 是一个实例,但我需要类型。

// Accessing members of protocol type value 'SomeProtocol.Type' is unimplemented
func useProp(x: SomeProtocol.Type) -> String {
    return x.prop 
}

考虑到“未实现”这个词,这可能是未来的工作方式。但是今天并不适用。

func useProp(x: SomeProtocol) -> String {
    // Accessing members of protocol type value 'SomeProtocol.Type' is unimplemented
    return x.dynamicType.prop
}

同样的事情。

今天,你真的需要将它挂在对象本身上,而不是使用staticclass

protocol SomeProtocol {
    var prop: String { get }
}

class C1: SomeProtocol {
    let prop = "This is One"
}

func useProp(x: SomeProtocol) -> String {
    return x.prop
}

在许多情况下,这并不可怕,因为类的值很可能也是该类的任何给定实例的值。而且这是我们今天所能做的所有事情。
当然,你的问题可能是你还没有实例,你需要这些信息来构建一个实例。这真的很困难,你应该重新考虑你的设计。通常你必须使用一些其他的模式,比如建造者模式。有关更多信息,请参见通用类型集合
现在你也说了:

或者从协议中“混合”

我不会在这里说“混合”。如果你真的像Ruby中的“mixin”一样,那么Swift中就没有这样的东西。Swift人们经常将此功能称为“默认实现”,目前还不可能(尽管我确实希望它最终会出现)。在协议中,你唯一能做的就是说实现者必须以某种方式提供这个方法。你无法为他们提供它。

Rob,我看到你编辑了我的答案,并将class更改为static,但在Xcode 6.2 / Swift 1.1中对我不起作用。那是Swift 1.2的变化吗? - Stefan Arentz
可能是这样;我在测试beta版本时,他们对类/静态做了一些更改。对于造成的困惑,我感到抱歉。 - Rob Napier
我想要这样做的原因是我想强制C1在其中实现prop - Incerteza
一旦您调用 C1.prop,您就强制 C1 实现 prop。除非某个函数接受协议(而不是特定的类),否则通过协议获得什么好处?为什么不只是让类实现该属性,而无需要求使用协议? - Rob Napier
抱歉,我的意思是我想强制它具有属性。 - Incerteza
由于class是引用类型,因此您不能在其中使用static关键字(仅允许在structenum中使用),而class let prop =“This is One”会出现错误:class variables not yet supported。我建议改用计算属性。 - Bartłomiej Semańczyk

2
protocol P {
    class var stProperty: String { get }
}

class C1 {
    class var stProperty: String {
        return = "my property1"
    }
}

class C2 {
    class var stProperty: String {
        return = "my property2"
    }
}

使用方法:

C2.prop //"my property2"

如果你尝试:

C2.prop = "new value" //"cannot assign to the result of this expression"

改成用"let"而不是"var"怎么样? - Incerteza
类属性只能在类内部声明;使用“static”来声明静态属性。在协议中正确的声明方式是 static var stProperty: String { get } - Julius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接