Implement Protocol Through Extension

how to extend a swift protocol with an extension so that classes get an implemented variable defined by the protocol

Currently your protocol defines isSharable as { get set }

protocol Sharable {
func share(name: String)
var isSharable: Bool { get set }
}

This means that when you construct your extension it is not actually conforming to the protocol

extension Sharable where Self: User {
func share(name: String) { print(name) }
var isSharable: Bool { return !name.isEmpty }
}

This is due to the fact that you have defined isSharable in your extension as a computed property. Computed properties are get only.

You can make your extension conform to the Sharable protocol by removing the set requirement. So your protocol would become:

protocol Sharable {
func share(name: String)
var isSharable: Bool { get }
}

Implement protocol through extension

Cocoa is written in Objective-C. Objective-C can't see Swift protocol extension code. So it's unaware of that implementation of imagePickerController:didFinishPickingImage:. If you want a delegate method to be called by Cocoa, you need to put it where Cocoa can see it.

swift protocol extension default implementation vs actual implementation in class

Having a default implementation for a required protocol function/property means that your conforming types won't have to implement that function/property, they can use the default implementation instead.

However, if a conforming type does implement the function/property, then the compiler will always call the more specific implementation, namely the one in your conforming class and not the default one.

So even if you stored an instance of MyClass2 in a variable of type MyProtocol, you'd still get the MyClass2 implementation when accessing the property on the variable.

let myClass2: MyProtocol = MyClass2()
type(of: myClass2).name // "Specific name"

The behaviour is different for non-required properties/functions declared and defined in a protocol extension. If you declare a property/function in the protocol extension only, then even if you provide a different implementation for that in a conforming class, you won't be able to access that implementation from a variable whose type is the protocol type rather than the specific conforming type.

protocol MyProtocol {
static var name: String { get }
}

extension MyProtocol {
static var name: String {
return "unnamed"
}

// Optional protocol requirement
static var nonRequired: String {
return "nonRequired"
}
}

// does not specify its own name
class MyClass: MyProtocol { }

//specifies its own name!
class MyClass2: MyProtocol {
static var name: String {
return "Specific name"
}

// Specific implementation
static var nonRequired: String {
return "Specific"
}
}

let myClass = MyClass()
MyClass.name

let myClass2: MyProtocol = MyClass2()
type(of: myClass2).name // "Specific name"
type(of: myClass2).nonRequired // "nonRequired"
MyClass2.nonRequired // "Specific"

How does protocol extension work in Swift?

I don't think there is even a need to inherit from NSObject if you are making a BaseClass to be inherited by other classes.

You can simply add classTag in the BaseClass itself, i.e.

class BaseClass {
var classTag: String {
return String(describing: type(of: self))
}
}

class SubClass: BaseClass {
func someFunc() {
print(self.classTag)
}
}

Another option can be to use protocol and protocol extension and provide the default definition of classTag, i.e.

protocol SomeProtocol {
var classTag: String { get }
}

extension SomeProtocol {
var classTag: String {
return String(describing: type(of: self))
}
}

Then, you can conform SomeProtocol to the classes wherever required, i.e.

class SubClass: SomeProtocol {
func someFunc() {
print(self.classTag)
}
}

In any case, inheriting from NSObject is unnecessary since you don't need any NSObject specific functionality for that.



Related Topics



Leave a reply



Submit