Swift Conform to Protocol Subclass

Swift conform to protocol subclass

Change

public protocol Restorable: AnyObject {
var storyItem: StoryItem? { get set } // adopter must declare as StoryItem
}

to

public protocol Restorable: AnyObject {
associatedtype T : StoryItem
var storyItem: T? { get set } // adopter must declare as StoryItem adopter
}

Now your code compiles. Full example:

public protocol StoryItem {
var id: Int64? { get }
}
public protocol Restorable: AnyObject {
associatedtype T : StoryItem
var storyItem: T? { get set }
}
public struct TextItem: StoryItem {
public var id: Int64?
public var text: String?
}
class ResizableLabel: UILabel, Restorable {
var storyItem: TextItem? // ok because TextItem is a StoryItem adopter
}

How to conform to protocol using subclass

You could use an associatedType that is constrained to be of type UIView.

protocol A: class {
associatedtype View: UIView
func configure(view: View)
}

Now in class B, since UILabel is a subclass of UIView, it's fine to do:

final class B: A {
init() {}

func configure(view: UILabel) {
...
}
}

Need to satisfy Swift protocol requirement by using a specific subclass of the requirement (or type that conforms to it)

To conform to protocol A, Model2 would need a member var a that allows storing a reference to anything conforming to protocol A, not just a reference to a Model1. So you can't do this.

Swift Protocol - Property type subclass

The problem is with the setter in the protocol.

Let's say you want to GET the panelView from LeftPanelController. That's fine, because LeftPanelView can do everything PanelView can do (and more).

If you want to SET the panelView of LeftPanelController though, you can give it any PanelView. Because you're defining the panelView variable as a LeftPanelView, the setter could sometimes fail.

To fix this, you could do the following in LeftPanelController:

var panelView: PanelView = LeftPanelView()

The implication of this is that you won't be able to access any methods or properties that are specific to LeftPanelView without casting it first. If that's not an issue, then this should fix your problem!

Swift protocol conformance requirements for subtypes

When you define a variable in a protocol and assign a type to it, that is going to be a concrete type, so you cannot change it to a subclass of that type when conforming to the protocol. The type of the variable declared in the conforming class must be the same type as declared in the protocol, it cannot be a covariant (inheritance related) type.

You can fix the second error by creating an associatedType for your Observer protocol, which inherits from ObserverObject then you can define object to be of the same type as your associated type. Then you can make your ObserverClass have a property object of type ObservedObjectSubclass.

class ObservedObject {}
class ObservedObjectSubclass: ObservedObject {}

protocol Observer {
associatedtype ObjectSubclass: ObservedObject
var object:ObjectSubclass { get }
}

class ObserverClass: Observer {
var object = ObservedObjectSubclass()
}

How to override swift protocol functions for subclasses (e.g. UILabel from UIView)

You can achieve that as below, You just need to expose aProtocol to Objective-c runtime for overriding its methods in the extension.

@objc protocol aProtocol {
typealias completionBlock = (_ finished:Bool)->()
func doSomething(completion: completionBlock)
}

extension UIView: aProtocol {
func doSomething(completion: (Bool) -> ()) {
print("Im an UIView")
}
}

extension UILabel {
override func doSomething(completion: (Bool) -> ()) {
// you can call super.doSomething(completion: completion)
print("im an UILabel")
}
}

extension UIImageView {
override func doSomething(completion: (Bool) -> ()) {
// you can call super.doSomething(completion: completion)
print("im an UIImageView")
}
}

Output:

Im an UIView
Im an UIView
im an UILabel
im an UIImageView

Swift: How can I make a function with a Subclass return type conform to a protocol, where a Superclass is defined as a return type?

Before you go much further, I'd recommend some background reading on covariance vs contravariance and the Liskov substitution principle.

  • Return types for methods overridden when subclassing are covariant: the subclass override of a method can return a subtype of the superclass method's return type.

  • Generic type parameters are invariant: a specialization can neither narrow nor expand the type requirements.

The relationship between a protocol and a concrete type that adopts it is more like generics than like subclassing, so return types declared in protocols are invariant, too. (It's hard to say exactly why on first read. Possibly something about existential vs constraint-only protocols?)

You can allow covariance in a protocol by specifying associated type requirements, though:

protocol SomeProtocol {
associatedtype ReturnType: SuperclassType
func someFunction(someParameter: SomeType) -> ReturnType
}

class SomeClass : SomeProtocol {
func someFunction(someParameter: SomeType) -> SubclassType { /*...*/ }
}

Now, it's clear that the return type of someFunction in a type adopting SomeProtocol must be either SuperclassType or a subtype thereof.

How is Self in protocol interpreted in subclass?

According to the documentation Self in this case will be A since A is the one conforming to the protocol, B is only doing it indirectly as a subclass of A.

So when A conforms to Copyable you are saying that A and all its subclasses must have an init(_ instance: A)

In a protocol declaration or a protocol member declaration, the Self type refers to the eventual type that conforms to the protocol.

You can actually test this by removing the required init(_ instance: A) init and you will get an error even if you have an init(_ instance: B), so since A is the class conforming to the protocol you must have an init where the instance argument is A



Related Topics



Leave a reply



Submit