Swift: The rules of being class (Xcode 6 Beta 7)


The three roles of the class keyword (updated 12 September 2014)

The class keyword has three roles:
  1. to declare a class
  2. to declare type methods and properties within a class
  3. to restrict a protocol to adoption by classes only

Rules of the first role

The rules for the first role are short and in fact there's only one
  1. place it before the name of your class when defining/declaring a new Type
however this one use does also enable the nesting of classes not only one inside the other, but also inside structs and enums. For example:
struct MyStruct {
    var a = MyClass()
    class MyClass {
        var a:Int = 10;
    }
}

MyStruct().a.a // returns 10

Rules of the second role

The rules for the second role are as follows:
  1. the class keyword can precede a function to transform it into a type method (i.e. a method that can be called via the type name without creating a class instance)
  2. the class keyword can precede a computed property to transform it into a type (or class) property 
  3. the class keyword cannot precede regular class properties, because they are not yet supported (according to the compiler)
  4. the class keyword cannot be used in structs or enums (there you use the static keyword)
  5. the class keyword is used in protocols to define required type methods and computed type properties
  6. "a type method can call another type method with the other method’s name, without needing to prefix it with the type name" (Apple)

Basic code examples

class SomeClass {
    class var description:String {
    return "computed class property"
    }
    class var property:String = "class property" // compiler warning: class variables not yet supported
    class func typeMethod() -> String {
        return "type method"
    }
}
In the above example there are three correct uses of the class keyword and one that is currently unsupported. It will not compile, whereas this code will work perfectly if cut and pasted into a Playground file:
class SomeClass {
    class var description:String {
    return "computed class property"
    }
       class func typeMethod() -> String {
        return "type method"
    }
}

SomeClass.description // returns "computed class property"
SomeClass.typeMethod() // returns "type method"
While it is possible to create computed properties with a getter and a setter, there isn't any real practical use for a setter at present. This is because without (regular) type variables the setter isn't able to change stored type properties.

Code example using protocols and the third role (update)

Following 3M's request (see comments below) I'm adding a further piece of code outlining how we'd include the requirement of computed class properties and methods in a protocol. I'm also including in this code an example of the third role of class, i.e. its use to restrict protocols so that they can only be used by classes. This is done simply by adding the class keyword, e.g. protocol Food: class. It is important, however, that the keyword comes before any other protocols that are being adopted by the current one.
enum FoodGroups {
    case Carbohydrates, Proteins, Fats, Fibre, Minerals, Vitamins
}

protocol Food: class {
    class var varieties:[String] {get}
    class func goesWith(type:FoodGroups) -> Bool
}

class Rice: Food {
    class var varieties:[String] {
    return ["white","brown"]
    }
    class func goesWith(type:FoodGroups) -> Bool {
        if type == .Carbohydrates {
            return false
        }
        else {
            return true
        }
    }
}

Rice.goesWith(.Proteins)
Rice.varieties
In brief, what happens is that the protocol specifies that every class that wishes to adopt it must have a type variable called 'varieties' (with a String array as its value). It must also have a type method called goesWith(), which takes an enum value from the FoodGroups enum and returns a Bool. The Rice class does both of these things and so the compiler allows it to adopt the Food protocol without complaint, but if we were to try and swap out type methods and type (computed) properties for regular instance methods and instance (computed) properties then the compiler would complain and not allow us to build the app.

Note: This is an entirely fictional piece of code and I make no claims to any knowledge of food science!


Endorse on Coderwall

Comments

  1. Your article seems incomplete or at the very least misleading. Why didn't you show examples of rules 4 and 5 of the second role of class?

    ReplyDelete
    Replies
    1. Thanks for your feedback, I can certainly add an example of a protocol. The static keyword I'm going to write about separately because it has its own set of rules.

      Mainly I want each of these keywords posts to be short and digestible so that people have a quick reference for what they can and can't do with each keyword.

      Again, thanks. It is good to hear how the posts come across.

      Delete

Post a Comment