Is there a difference between extending a class that conforms to the VS protocol, which extends the protocol based on a similar condition?

I went through this link.

But I do not understand the logical difference between the code snippets below:

1. Extension ONLY of these UIViewControllers that conform to the ErrorPopoverRenderer protocol.

protocol ErrorPopoverRenderer { func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool) } extension UIViewController: ErrorPopoverRenderer { //Make all the UIViewControllers that conform to ErrorPopoverRenderer have a default implementation of presentError func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool) {} } 

2. Protocol extension for ONLY those UIViewControllers that match it.

 extension ErrorPopoverRenderer where Self: UIViewController { func presentError() { } } 

In any case, any subclass of the UIViewController that conforms to the protocol will have a default implementation, but in a UIviewcontroller extension or protocol extension. What is the logical difference? Please correct me if I am wrong

+5
source share
2 answers

The difference is that the first one:

 extension UIViewController: ErrorPopoverRenderer { } 

actually extends the UIViewController class, so each instance of the UIViewController now has access to protocol methods and properties. This does not mean that it will expand the class that implements the protocol; it does mean that right now you are implementing the protocol for this class . Usually you need to implement some of the methods and properties of this extension.

Where in the second:

 extension ErrorPopoverRenderer where Self: UIViewController {} 

you are actually adding methods and properties to a UIViewController that implements the ErrorPopoverRenderer protocol.

Basically, you first extend the class using the entire protocol implementation, and in the second, you extend the class, but only if this class or subclass implements the ErrorPopoverRenderer protocol.

+3
source

1

First of all, you create the ErrorPopoverRenderer protocol with a plan for the presentError(...) method. Then you extend the UIViewController class to conform to this protocol, implementing the (required) plan for the presentError(...) method.

This means that you can subclass UIViewController) with the additional protocol restriction ErrorPopoverRenderer for the subclass. If the UIViewController not been extended to comply with the ErrorPopoverRenderer protocol, the following code in your example will result in a compile-time error ( ... does not comply to protocol ErrorPopoverRenderer )

 class KrakenViewController: UIViewController, ErrorPopoverRenderer { func failedToEatHuman() { //… //Throw error because the Kraken sucks at eating Humans today. presentError(ErrorOptions(message: "Oh noes! I didn't get to eat the Human!", size: CGSize(width: 1000.0, height: 200.0))) //Woohoo! We can provide whatever parameters we want, or no parameters at all! } } 

However, there is a possible problem with this method, as shown in your link:

Now we must implement each parameter every time we want to present an ErrorView. Such a crap, because we can not value for the declarations of protocol functions.

Thus, the ErrorPopoverRenderer protocol ErrorPopoverRenderer not intended solely for the use of UIViewController : s (or its subclasses), then the above solution is not very general.

2

If we want to use ErrorPopoverRenderer more widely, we will place specific drawings for each type of class that could use the protocol in protocol extensions. This is very neat, since the more specific parts of the ErrorPopoverRenderer drawings for the presentError() method can be set differently for different classes that may correspond to the protocol, and the presentError() method can be made more minimalistic.

I quote for example:

Using Self here means that this extension will only ever take place if and only if the converter inherits from the UIViewController. This gives us the opportunity to assume that ErrorPopoverRenderer is indeed a UIViewController without even extending the UIViewController.

In this method, since the code now knows (we already, in 1.) that it is a view controller that will call presentError() , we can place the specific UIViewController material directly in the implementation of the drawing, and we don’t need to send it as a long list arguments.

Therefore, 2. for this specific use, it is a kind of more β€œgeneral” approach in the sense that we slightly minimize code duplication (calling presentError() vs presentError(... lots of args ...) from several different UIViewController : s )

+1
source

Source: https://habr.com/ru/post/1239257/


All Articles