Swift Language Class-Only Protocols


Example

A protocol may specify that only a class can implement it through using the class keyword in its inheritance list. This keyword must appear before any other inherited protocols in this list.

protocol ClassOnlyProtocol: class, SomeOtherProtocol {
    // Protocol requirements 
}

If a non-class type tries to implement ClassOnlyProtocol, a compiler error will be generated.

struct MyStruct: ClassOnlyProtocol { 
    // error: Non-class type 'MyStruct' cannot conform to class protocol 'ClassOnlyProtocol'  
}

Other protocols may inherit from the ClassOnlyProtocol, but they will have the same class-only requirement.

protocol MyProtocol: ClassOnlyProtocol {
    // ClassOnlyProtocol Requirements
    // MyProtocol Requirements
}

class MySecondClass: MyProtocol {
    // ClassOnlyProtocol Requirements
    // MyProtocol Requirements
}

Reference semantics of class-only protocols

Using a class-only protocol allows for reference semantics when the conforming type is unknown.

protocol Foo : class {
    var bar : String { get set }
}

func takesAFoo(foo:Foo) {

    // this assignment requires reference semantics,
    // as foo is a let constant in this scope.
    foo.bar = "new value"
}

In this example, as Foo is a class-only protocol, the assignment to bar is valid as the compiler knows that foo is a class type, and therefore has reference semantics.

If Foo was not a class-only protocol, a compiler error would be yielded – as the conforming type could be a value type, which would require a var annotation in order to be mutable.

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

func takesAFoo(foo:Foo) {
    foo.bar = "new value" // error: Cannot assign to property: 'foo' is a 'let' constant
}

func takesAFoo(foo:Foo) {
    var foo = foo // mutable copy of foo
    foo.bar = "new value" // no error – satisfies both reference and value semantics
}

Weak variables of protocol type

When applying the weak modifier to a variable of protocol type, that protocol type must be class-only, as weak can only be applied to reference types.

weak var weakReference : ClassOnlyProtocol?