36

I had following confusion. As far as I know the main difference between static and class keywords when declaring method is that the second one could be overridden in subclasses.

The problem

However when I declare a protocol in Swift 1.2 like this:

protocol MyProtocol
{
    class func dummyClassMethod()
}

compiler gives an error:

Class methods are only allowed within classes; use 'static' to declare a static method

The error is pretty descriptive as obviously MyProtocol is not a class, however I want to make a class func part of the protocol.

What I've tried

I've found that if I declare interface in protocol as static, compiler is happy and I could use this static method in all classes that adopt this protocol:

protocol MyProtocol
{
    static func dummyClassMethod()
}

The question

So my question basically is is this right? This declaration states that my class method cannot be overridden in children, however in my implementation I could write and use the following:

class ClassA: MyProtocol
{
    class func dummyClassMethod() {

    }
}

class ClassB: ClassA
{
    override class func dummyClassMethod() {

    }
}

and now my dummyClassMethod is not static anymore...

  1. Compiler is Ok and everything works - but why?

  2. Is it specific to the fact that interface itself is static, however it's implementation is not?

  3. Is there a better alternative for class func in protocols?

Objective-C solution

In ObjC this is pretty easy and compile & run flawlessly:

@protocol MyProtocol 

+(void)dummyClassMethod;

@end
hris.to
  • 6,235
  • 3
  • 46
  • 55

3 Answers3

39

You can review Apple's Documentation (subsection Method Requirements).

There says:

As with type property requirements, you always prefix type method requirements with the static keyword when they are defined in a protocol. This is true even though type method requirements are prefixed with the class or static keyword when implemented by a class

In practice, You can do it as follow:

First, declare your protocol:

protocol SomeProtocol {
    static func someMethod()
}

Then, in your class you've 2 options:

First:

class SomeClass : SomeProtocol {
    class func someMethod()
}

Second:

class SomeClass : SomeProtocol {
    static func someMethod()
}

I hope, this may clarify your doubt..

eMdOS
  • 1,693
  • 18
  • 23
  • 2
    It's a little bizarre that you can declare the `func` `static` in the protocol, but simply ignore that fact and use it as a `class func`. Especially since `static` implies `final class` and in a protocol the func is anything but final since it must be implemented. Anyone have any insight into why Apple would design the language like this? – Sandy Chapman Nov 24 '15 at 01:39
  • 1
    @SandyChapman I think you are trying to compare Swift vs Java, don't do that, just read Apple Doc, my answer is based on that. I know this is not possible in Java, but Swift is not Java. Many things have different behaviors like `private`, `public`, `internal`, `final`, `static`, etc., just read the doc. – eMdOS Nov 24 '15 at 16:01
  • 2
    No, I'm not trying to compare to Java. In Swift, `static` is equivalent to `final class` when used in classes, but has a different meaning altogether when used in a protocol. I'm saying Swift's usage of requiring `static` in protocols doesn't really make sense, when you can ignore the implicit `final` that it has when overriding in a class. It would make more sense if protocols required using `class`, not `static` as it would leave it up to the implementor to determine if they wanted the method to be `final`. – Sandy Chapman Nov 24 '15 at 16:05
  • Actually `final` and `static` have the similar behavior, what I've seen, in my experience, Apple's convention is to use `final` for `inheritance` (`classes` **Preventing Overrides** -> https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html), and `static` for `conformance` (`protocols` **Method Requirements** -> https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html). – eMdOS Nov 24 '15 at 17:14
  • Just pointing the docs doesn't really answer the question. IMHO this should be mark with `class` keyword inside protocols and later when implementing decide whether children can override it. Probably they chosen this because protocol can be applied to enum and structs also and class keyword could be confusing. – hris.to Jun 16 '16 at 09:09
  • @hris.to: It's things like this that make me see Swift not so much as a computer language but more as an adventure game. (The above explanation skips the need to use "class" on the func if you're going to use derived classes because Swift won't let you override a static func. And the fact that if the protocol is applied to a struct then you have to use "static" on the func because "class" is not allowed.) – RenniePet Jan 08 '17 at 14:11
3

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol doesn’t actually provide an implementation for any of these requirements—it only describes what an implementation will look like. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements.

After this protocol definition it becomes reasonable that

As with type property requirements, you always prefix type method requirements with the static keyword when they are defined in a protocol. This is true even though type method requirements are prefixed with the class or static keyword when implemented by a class...

Ilia
  • 1,434
  • 15
  • 22
1

To make protocol method static and final implement that method with static keyword

class ClassA: MyProtocol{

    static func dummyClassMethod() {

    }
} 

and now you cant override dummyClassMethod function anymore. If you want to prevent overriding only you must declare protocol method as final. About class functions, they were not fully supported in Swift 1.0 and now in Swift 1.2 I think that they are moving towards static functions

Zell B.
  • 10,266
  • 3
  • 40
  • 49
  • final keyword can be used only in classes and class members. Hence same problem as with class keyword. – hris.to May 14 '15 at 11:03
  • But still if you implement protocol method as static make it static and final and that will solve the problem your problem – Zell B. May 14 '15 at 11:11
  • Well ti will solve it on implementation layer, not in interface layer. I'll have to be sure each implementation of protocol implements it as static final, rather than make the interface itself requiring this. – hris.to May 14 '15 at 11:15
  • As I said just don't mess with class functions anywhere in your project since they are not fully supported yet and use statics only to achieve same behavior. – Zell B. May 14 '15 at 11:32