Swift 4 generic, referencing self - swift

I'm considering the following structure using Swift 4:
class BaseClass {
// abstract function
func doSomething<T: BaseClass>(with object: T) {}
}
class SubClass: BaseClass {
var title: String = "hello world"
// implementation
override func doSomething<T: BaseClass>(with object: T) {
// do something with object
// can I access object.title here?
}
}
In the above snippet the object.title property is not accessible, because apparently type of object property is BaseClass, not SubClass.
I assume the function parameter type should be set as Self, such as:
func doSomething(with object: Self) {}
but the following error occurs while compilation.
'Self' is only available in a protocol or as the result of a method in a class; did you mean 'BaseClass'?
Is there a way to reference type of self while overriding functions from base class?
Edit
So my question is whether we can access SubClass's properties inside functions that overrides super class's functions (as object.title property is in SubClass implementation). I was considering a whole lot of classes that inherit base class, so I thought it might be useful to have functions that interacts with another instance with the same type when called.

You cannot create a function kike func doSomething(with object: Self) {} since it would mean different things in those classes (and thus, would not overwrite each other semantically)
Think about calling the subclass with a BaseClass object, that is not a Subclass, if you had a method with Self like you showed in your snippet, it would be implemented by the supperclass, but the subclass would not implement it anymore.
But, you can cast it like this in the subclass:
override func doSomething<T: BaseClass>(with object: T) {
guard let subClass = object as? SubClass else { return }
print("\(title): \(subClass.title)")
}

Related

Swift Protocol Extension unexpected behavior [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.

function declared in a protocol, in a protocol extension, and in a class/subclass [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 protocol extension method is called instead of method implemented in subclass

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.

Cannot override initialiser in subclass of generic class

I'd like to make a subclass of a generic class that is itself a subclass but I cannot override the initializer.
To clarify:
class BaseClass {
init(printMe: String) {
print(printMe)
}
}
class GenericClass<T>: BaseClass {
var object: T?
}
class NotGenericClass: GenericClass<NSNumber> {
override init(printMe: String) { // <- Error here
super.init(printMe: printMe)
// More setup
}
}
let a = NotGenericClass(printMe: "Print this")
a.object = NSNumber(int: 1)
The override init(printMe: String) line in NotGenericClass gives the following error:
Initializer does not override a designated initializer from its superclass
If GenericClass did not take a type parameter, this code would work. Is this a bug with Swift or am I misunderstanding how subclassing generic classes should work?
It seems that GenericClass doesn't automatically inherit the initializer in this case.
This makes it work:
class GenericClass<T>: BaseClass {
var object: T?
// Explicitly provide an initializer
override init(printMe: String) {
super.init(printMe: printMe)
}
}
This isn't clear from the Automatic Initializer Inheritance section of the docs, which claims that "If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers". You might want to file a bug.

How to tell if a subclass overrides a method in Swift

I’ve got a Swift class Parent that has a method doSomething() and I want to detect (in Parent) if a subclass has overridden doSomething(). How do I do that?
class Parent {
func doSomething() {}
func subclassOverridesDoSomething() -> Bool {
// what goes here?
return true
}
}
class Child: Parent {
override func doSomething() {}
}
I know I can do this with NSObject or even the Objective C runtime functions, but how can I do it with Swift classes?
You can use the Objective-C runtime provided you expose the function with dynamic:
class Parent {
func doSomething() {}
func subclassOverridesDoSomething(t:Parent.Type) -> Bool {
let originalMethod = class_getInstanceMethod(t, "doSomething")
return originalMethod != nil
}
}
class Child: Parent {
dynamic override func doSomething() {}
}
Parent().subclassOverridesDoSomething(Child.self)
If you omit dynamic, it won't work because Objective-C can't see the method.
Well Swift doesn't really offer methods to do that.
Also in my opinion, there is no disadvantage in using Objective-c methods like method_getImplementation or the NSObject. You will have to use the methods objective-c offers you to solve your problem.
For example:
let selector = Selector("viewWillAppear:")
let originalMethod = class_getInstanceMethod(YourClass, selector)