Swift Declare Class Func in Protocol - ios

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...
Compiler is Ok and everything works - but why?
Is it specific to the fact that interface itself is static, however
it's implementation is not?
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

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..

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...

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

Related

Why implement can't override methods in Swift? [duplicate]

I've encountered a problem that is explained in the code below (Swift 3.1):
protocol MyProtocol {
func methodA()
func methodB()
}
extension MyProtocol {
func methodA() {
print("Default methodA")
}
func methodB() {
methodA()
}
}
// Test 1
class BaseClass: MyProtocol {
}
class SubClass: BaseClass {
func methodA() {
print("SubClass methodA")
}
}
let object1 = SubClass()
object1.methodB()
//
// Test 2
class JustClass: MyProtocol {
func methodA() {
print("JustClass methodA")
}
}
let object2 = JustClass()
object2.methodB()
//
// Output
// Default methodA
// JustClass methodA
So I would expect that "SubClass methodA" text should be printed after object1.methodB() call. But for some reason default implementation of methodA() from protocol extension is called. However object2.methodB()call works as expected.
Is it another Swift bug in protocol method dispatching or am I missing something and the code works correctly?
This is just how protocols currently dispatch methods.
A protocol witness table (see this WWDC talk for more info) is used in order to dynamically dispatch to implementations of protocol requirements upon being called on a protocol-typed instance. All it is, is really just a listing of the function implementations to call for each requirement of the protocol for a given conforming type.
Each type that states its conformance to a protocol gets its own protocol witness table. You'll note that I said "states its conformance", and not just "conforms to". BaseClass gets its own protocol witness table for conformance to MyProtocol. However SubClass does not get its own table for conformance to MyProtocol – instead, it simply relies on BaseClass's. If you moved the : MyProtocol down to the definition of SubClass, it would get to have its own PWT.
So all we have to think about here is what the PWT for BaseClass looks like. Well, it doesn't provide an implementation for either of the protocol requirements methodA() or methodB() – so it relies on the implementations in the protocol extension. What this means is that the PWT for BaseClass conforming to MyProtocol just contains mappings to the extension methods.
So, when the extension methodB() method is called, and makes the call out to methodA(), it dynamically dispatches that call through the PWT (as it's being called on a protocol-typed instance; namely self). So when this happens with a SubClass instance, we're going through BaseClass's PWT. So we end up calling the extension implementation of methodA(), regardless of the fact that SubClass provides an implementation of it.
Now let's consider the PWT of JustClass. It provides an implementation of methodA(), therefore its PWT for conformance to MyProtocol has that implementation as the mapping for methodA(), as well as the extension implementation for methodB(). So when methodA() is dynamically dispatched via its PWT, we end up in its implementation.
As I say in this Q&A, this behaviour of subclasses not getting their own PWTs for protocols that their superclass(es) conform to is indeed somewhat surprising, and has been filed as a bug. The reasoning behind it, as Swift team member Jordan Rose says in the comments of the bug report, is
[...] The subclass does not get to provide new members to satisfy the conformance. This is important because a protocol can be added to a base class in one module and a subclass created in another module.
Therefore if this was the behaviour, already-compiled subclasses would lack any PWTs from superclass conformances that were added after the fact in another module, which would be problematic.
As others have already said, one solution in this case is to have BaseClass provide its own implementation of methodA(). This method will now be in BaseClass's PWT, rather than the extension method.
Although of course, because we're dealing with classes here, it won't just be BaseClass's implementation of the method that's listed – instead it will be a thunk that then dynamically dispatches through the class' vtable (the mechanism by which classes achieve polymorphism). Therefore for a SubClass instance, we'll wind up calling its override of methodA().
A very short answer that a friend shared with me was:
Only the class that declares the conformance gets a protocol witness table
Meaning a subclass having that function has no effect on how the protocol witness table is setup.
The protocol witness is a contract only between the protocol, it's extensions, and the concrete class that implements it.
Well I suppose the subclass method A is not polymorphic because you can't put the override keyword on it, since the class doesn't know the method is implemented in an extension of the protocol and thus doesn't let you override it. The extension method is probably stepping on your implementation in runtime, much like 2 exact category methods trump each other with undefined behavior in objective C. You can fix this behavior by adding another layer in your model and implementing the methods in a class rather than the protocol extension, thus getting polymorphic behavior out of them. The downside is that you cannot leave methods unimplemented in this layer, as there is no native support for abstract classes (which is really what you're trying to do with protocol extensions)
protocol MyProtocol {
func methodA()
func methodB()
}
class MyProtocolClass: MyProtocol {
func methodA() {
print("Default methodA")
}
func methodB() {
methodA()
}
}
// Test 1
class BaseClass: MyProtocolClass {
}
class SubClass: BaseClass {
override func methodA() {
print("SubClass methodA")
}
}
let object1 = SubClass()
object1.methodB()
//
// Test 2
class JustClass: MyProtocolClass {
override func methodA() {
print("JustClass methodA")
}
}
let object2 = JustClass()
object2.methodB()
//
// Output
// SubClass methodA
// JustClass methodA
Also relevante answer here: Swift Protocol Extensions overriding
In your code,
let object1 = SubClass()
object1.methodB()
You invoked methodB from an instance of SubClass, but SubClass does not have any method named methodB. However its super class, BaseClass conform to MyProtocol, which has a methodB methodB.
So, it will invoke the methodB from MyProtocal. Therefore it will execute the methodA in extesion MyProtocol.
To reach what you expect, you need implement methodA in BaseClass and override it in SubClass, like the following code
class BaseClass: MyProtocol {
func methodA() {
print("BaseClass methodA")
}
}
class SubClass: BaseClass {
override func methodA() {
print("SubClass methodA")
}
}
Now, output would become
//Output
//SubClass methodA
//JustClass methodA
Although the method can reach what you expect, but I'm not sure this kind of code struct is recommended.

Swift: static property in protocol extension CAN be overridden, but why?

I watched "Protocol-Oriented Programming in Swift" and read the related docs, but I still think there is a conflict in the following sample code (try it in a Playground).
protocol X {
// The important part is "static" keyword
static var x: String { get }
}
extension X {
// Here "static" again
static var x: String {
get {
return "xxx"
}
}
}
// Now I'm going to use the protocol in a class, BUT
// in classes "static" is like "final class",
// i.e. CAN'T BE OVERRIDDEN, right?
// But I'd prefer to have the ability to override that property,
// so I'll try to use "class" keyword.
// Will it break the program? (spoiler: no!)
class Y: X {
// Here we are allowed to use "class" keyword (but why?).
class var x: String {
get {
return "yyy"
}
}
}
class Z: Y {
override class var x: String {
get {
return "zzz"
}
}
}
class Test<T: X> {
func test() -> String {
return T.x
}
}
// And finally the property is successfully overridden (but why?).
print(Test<Z>().test()) // "zzz\n"
Does this actually mean that static keyword from protocol (and possible default implementation) can be legitimately replaced with class keyword when the protocol used in classes? Do you know any references confirming that?
From Language Reference / Declarations we know the following.
Function Declaration
...
Special Kinds of Methods
...
Methods associated with a type rather than an instance of a type must be marked with the static declaration modifier for enumerations and structures or the class declaration modifier for classes.
I.e. the static keyword is (mainly) for enumerations and structures and the class keyword is for classes.
There is also such a note:
Type Variable Properties
...
NOTE
In a class declaration, the keyword static has the same effect as marking the declaration with both the class and final declaration modifiers.
I.e. the static keyword actually can be used in class declaration and will mean final class.
So what about protocols?
Protocol Method Declaration
...
To declare a class or static method requirement in a protocol declaration, mark the method declaration with the static declaration modifier. Classes that implement this method declare the method with the class modifier. Structures that implement it must declare the method with the static declaration modifier instead. If you’re implementing the method in an extension, use the class modifier if you’re extending a class and the static modifier if you’re extending a structure.
Here the docs state that we should replace the static keyword from protocol declaration with the class keyword when implementing the protocol in a class or a class extension (and this is the exact answer to the original question).
Bonus
There are two cases in which protocol adoption will be restricted to classes only. The first (and the least explicit) is when a protocol includes optional members:
Protocol Declaration
...
By default, types that conform to a protocol must implement all properties, methods, and subscripts declared in the protocol. That said, you can mark these protocol member declarations with the optional declaration modifier to specify that their implementation by a conforming type is optional. The optional modifier can be applied only to protocols that are marked with the objc attribute. As a result, only class types can adopt and conform to a protocol that contains optional member requirements. ...
And the second (explicit; the next paragraph):
To restrict the adoption of a protocol to class types only, mark the protocol with the class requirement by writing the class keyword as the first item in the inherited protocols list after the colon. ...
But neither of them changes the rules considering the static and the class keywords applicability.

Get the class type that implements a protocol swift

So what I am trying to do is make it easy for me to implement many custom UITableViewCells on one tableView, to do this I wanted to create a protocol that would facilitate filling out the function:
- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier
my protocol so far looks like this:
protocol TableViewCellClassReportingProtocol: class {
func reuseID() -> String
}
extension TableViewCellClassReportingProtocol {
static func classObject() -> AnyClass? {
return self.class
}
}
however I am having issues with getting the class type even thought I specify that this protocol must be implemented by a class. Any suggestions, I may be approaching this the wrong way
So this was close to the right answar and let me both elaborate and give credit to Charles A.
dynamicType is part of the answar! great call!
the function implamintation also had to change, because of subclassing and static really meaning "class final"
Protocol for class method
the override points must be
override class func reuseID() -> String

How can I create a Set of delegate protocol items in Swift?

Let's assume I have five UIView objects which all conform to a particular protocol. I have an object which should maintain a list of these objects, and message them all when necessary.
protocol MyProtocol: AnyObject {
func doSomething()
}
The problem is, when I go to add these UIViews to a Set variable, the compiler produces an error because MyProtocol does not conform to Hashable. I can understand the reasoning for this, can anyone think of good ways to overcome this? In the meantime I considered using NSHashTable instead, but you lose the nice enumeration features of Sets.
Updating answer to post some sample code (this is still not working)
protocol MyProtocol: class, AnyObject {
func doSomething()
}
class MyClass {
var observers: Set<MyProtocol> = Set<MyProtocol>()
}
As you are defining protocol for class so you need to write 'class' keyword before inheriting any other protocol:
protocol MyProtocol: AnyObject, Hashable{
func doSomething()
}
class MyClass<T: MyProtocol> {
var observers: Set<T> = Set<T>()
}
Change your protocol to this and it will work fine.
You can refer Apple Documentation for further details.

Override var conforming to a protocol with a var conforming to a child of the overridden var protocol

This is my inheritance structure
Protocols
protocol BaseProtocol {
}
protocol ChildProtocol: BaseProtocol {
}
Classes
class BaseClass: NSObject {
var myVar: BaseProtocol!
}
class ChildClass: BaseClass {
override var myVar: ChildProtocol!
}
I'm receiving a compiler error:
Property 'myVar' with type 'ChildProtocol!' cannot override a property with type 'BaseProtocol!'
What is the best approach to achieve this?
UPDATE
I updated the question trying to implement the solution with generics but it does not work :( This is my code (now the real one, without examples)
Protocols
protocol TPLPileInteractorOutput {
}
protocol TPLAddInteractorOutput: TPLPileInteractorOutput {
func errorReceived(error: String)
}
Classes
class TPLPileInteractor<T: TPLPileInteractorOutput>: NSObject, TPLPileInteractorInput {
var output: T!
}
And my children
class TPLAddInteractor<T: TPLAddInteractorOutput>: TPLPileInteractor<TPLPileInteractorOutput>, TPLAddInteractorInput {
}
Well, inside my TPLAddInteractor I can't access self.output, it throws a compiler error, for example
'TPLPileInteractorOutput' does not have a member named 'errorReceived'
Besides that, when I create the instance of TPLAddInteractor
let addInteractor: TPLAddInteractor<TPLAddInteractorOutput> = TPLAddInteractor()
I receive this other error
Generic parameter 'T' cannot be bound to non-#objc protocol type 'TPLAddInteractorOutput'
Any thoughts?
#tskulbru is correct: it can't be done, and this has nothing to do with your protocols. Consider the example below, which also fails…this time with Cannot override with a stored property 'myVar':
class Foo {
}
class Goo: Foo {
}
class BaseClass: NSObject {
var myVar: Foo!
}
class ChildClass: BaseClass {
override var myVar: Foo!
}
To understand why, let's reexamine the docs:
Overriding Properties
You can override an inherited instance or class property to provide
your own custom getter and setter for that property, or to add
property observers to enable the overriding property to observe when
the underlying property value changes.
The implication is that if you are going to override a property, you must write your own getter/setter, or else you must add property observers. Simply replacing one variable type with another is not allowed.
Now for some rampant speculation: why is this the case? Well, consider on the one hand that Swift is intended to be optimized for speed. Having to do runtime type checks in order to determine whether your var is in fact a Foo or a Bar slows things down. Then consider that the language designers likely have a preference for composition over inheritance. If both of these are true, it's not surprising that you cannot override a property's type.
All that said, if you needed to get an equivalent behavior, #tskulbru's solution looks quite elegant, assuming you can get it to compile. :)
I don't think you can do that with protocols
The way i would solve the problem you are having is with the use of generics. This means that you essentially have the classes like this (Updated to a working example).
Protocols
protocol BaseProtocol {
func didSomething()
}
protocol ChildProtocol: BaseProtocol {
func didSomethingElse()
}
Classes
class BaseClass<T: BaseProtocol> {
var myProtocol: T?
func doCallBack() {
myProtocol?.didSomething()
}
}
class ChildClass<T: ChildProtocol> : BaseClass<T> {
override func doCallBack() {
super.doCallBack()
myProtocol?.didSomethingElse()
}
}
Implementation/Example use
class DoesSomethingClass : ChildProtocol {
func doSomething() {
var s = ChildClass<DoesSomethingClass>()
s.myProtocol = self
s.doCallBack()
}
func didSomething() {
println("doSomething()")
}
func didSomethingElse() {
println("doSomethingElse()")
}
}
let foo = DoesSomethingClass()
foo.doSomething()
Remember, you need a class which actually implements the protocol, and its THAT class you actually define as the generic type to the BaseClass/ChildClass. Since the code expects the type to be a type which conforms to the protocol.
There are two ways you can go with your code, depending what you want to achieve with your code (you didn't tell us).
The simple case: you just want to be able to assign an object that confirms to ChildProtocol to myVar.
Solution: don't override myVar. Just use it in ChildClass. You can do this by design of the language Swift. It is one of the basics of object oriented languages.
Second case: you not only want to enable assigning instances of ChildProtocol, you also want to disable to be able to assign instances of BaseProtocol.
If you want to do this, use the Generics solution, provided here in the answers section.
If you are unsure, the simple case is correct for you.
Gerd

Resources