4

I want to be able to have the classes which have a static property (field) which is either inherited from the base class or "mixed" from a protocol. And every class should have it's own implementation of that property. Is it possible? Preferably, it to be immutable.

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

class C2 {
  static let stProperty = "my prorepty2"
}
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
Incerteza
  • 32,326
  • 47
  • 154
  • 261

3 Answers3

2

Sure you can do that with a protocol:

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

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

Btw I agree with Rob Napier below that this is a bit off a oddball feature. I do think there are probably use-cases for it, but I also think those can be better implemented with other language features

Stefan Arentz
  • 34,311
  • 8
  • 67
  • 88
  • maybe it's better to convert SomeProtocol to a class? – Incerteza Mar 13 '15 at 14:30
  • That would depend on what problem you're trying to solve. In many cases, inheritance is the wrong solution. The question is whether all the things are fundamentally "a kind of X" (in which case inheritance is good) or if they just "do X-like things" (in which case a protocol is the right answer). When in doubt, use protocol. – Rob Napier Mar 13 '15 at 15:01
2

It's possible, but it's really hard to make this useful in Swift. How do you plan to refer to this property? Let's start with a super-simple implementation:

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

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

Great. So now I want a function that uses this:

func useProp(x: SomeProtocol) -> String {
    return x.prop
    // 'SomeProtocol' does not have a member named 'prop'
}

That doesn't work. x is an instance, but I want the type.

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

This is probably how it will work some day given the word "unimplemented." But it doesn't work today.

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

Same thing.

Today, you really have to hang this on the object itself and not use static or class:

protocol SomeProtocol {
    var prop: String { get }
}

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

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

That's not so terrible in many cases, since the value for the class is probably also the value for any given instance of the class. And it's really all we can do today.

Of course your problem might be that you don't have an instance yet and you need this information to build an instance. That's really hard today and you should probably rethink your design. You'll generally have to use some other pattern like a Builder. See Generic Types Collection for more.

Now you also said:

or "mixed" from a protocol

I wouldn't say "mixed" here. If you really mean this like a Ruby "mixin", there is no such thing in Swift today. Swift folks often refer to this feature as "default implementation," and it's not currently possible (though I do expect it to come eventually). The only thing you can do in the protocol is say that the implementor has to provide this method somehow. You can't provide it for them.

Community
  • 1
  • 1
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Rob I see you edited my answer and changed `class` to `static` but that does not work for me in Xcode 6.2 / Swift 1.1. Is that a Swift 1.2 change? – Stefan Arentz Mar 13 '15 at 14:02
  • It might be; I was testing on the beta, and they did make some changes around class/static. Sorry for the confusion. – Rob Napier Mar 13 '15 at 14:08
  • The reason I want this is I want to force C1 to implement `prop` in it. – Incerteza Mar 13 '15 at 14:43
  • As soon as you call `C1.prop`, you've forced `C1` to implement `prop`. Unless some function accepts the protocol (rather than the specific class), what benefit are you getting via the protocol? Why not just have the classes implement the property without a protocol requiring it? – Rob Napier Mar 13 '15 at 14:56
  • Sorry, I meant rather I want to force it to have prop. – Incerteza Mar 13 '15 at 16:07
  • Since `class` is reference type you cannot use there `static` keyword (it is allowed only for a `struct` or `enum`) and `class let prop = "This is One"` gives an error: `class variables not yet supported`. I suggest to use computed property instead – Bartłomiej Semańczyk Mar 14 '15 at 07:41
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"
    }
}

Usage:

C2.prop //"my property2"

If you try:

C2.prop = "new value" //"cannot assign to the result of this expression"
Bartłomiej Semańczyk
  • 59,234
  • 49
  • 233
  • 358
  • how about making it "let" instead of "var"? – Incerteza Mar 14 '15 at 08:14
  • "Class properties are only allowed within classes; use 'static' to declare a static property" - The correct declaration within a protocol would be `static var stProperty: String { get }` – Julius Mar 22 '19 at 16:21