I'm wondering why protocols are used in swift. In every case I've had to use one so far (UICollectionViewDelegate, UICollectionViewDataSource) I've noted that they don't even have to be added to the class declaration for my code to work. All they do is make it such that your class needs to have certain methods in it so that it can compile. Beats me why this is useful other then as a little post it note to help you keep track of what your classes do.
I'm assuming I'm wrong though. Would anyone care to point out why to me please?
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.
So it's basically an interface, right?
You use an interface when you want to define a "contract" for your code. In most cases, the purpose of this is to enable multiple implementations of that contract. For example, you can provide a real implementation, and a fake one for testing.
Further Reading
Protocols
What is the point of an Interface?
It allows flexible linkage between parts of code. Once the protocol is defined it can be used by code that doesn't need to know what will be done when the methods are called or exactly what object (or struct or enum) is actually being used. An alternative approach could be setting callbacks or blocks but by using a protocol as complete set of behaviours can be grouped and documented.
Some other code will typically create the concrete instance and pass it to the code expecting the protocol (sometimes the concrete instance will pass itself). In some cases neither the implementation of the code using it need to be aware of each other and it can all be set up by some other code to keep it reusable and testable.
It might be possible to do this in some languages by duck typing which is to say that a runtime inspection could allow a object to act in such a context without particular declaration but this is probably not possible to do at compile time in all cases and it could also be error prone if worked out implicitly.
Related
The Interfaces rule in the official Go Code Review Comments document says that packages should return concrete types rather than interfaces. The motivation for this is so that:
...new methods can be added to implementations without requiring extensive refactoring.
which I accept could be a good thing.
But what if a type I'm writing has a dependency without which it cannot serve its purpose? If I export the concrete type, developers will be able to instantiate instances without that dependency. To code defensively for the missing dependency, I then have to check for it in every method implementation and return errors if it is absent. If the developer missed any hints not to do this in my documentation, she or he won't learn about the problem until run time.
On the other hand, if I declare and return an interface with the methods the client needs, I can unexport the concrete type and enforce the use of a factory method which accepts the dependency as an argument and returns the interface plus an error. This seems like a better way to ensure correct use of the package.
Am I somehow not properly getting into the go spirit by thinking like this? Is the ethic of the language that it's okay to have a less-than-perfect encapsulation to give more flexibility to developers?
You may expect developers to read the doc you provide, and you may rely on them following the rules you set. Yes, lazy developers will bump their head from time to time, but the process of developing isn't without having to learn. Everything cannot be made explicit or enforced, and that's all right.
If you have an exported struct type Example and you provide a constructor function NewExample(), that's a clear indication that NewExample() should be used to construct values of Example. Anyone attempting to construct Example manually is expected to know what fields must be set for it to be "operational". The aim is always to make the zero value fully functional, but if that can't be achieved, the constructor function is the idiomatic way to go.
This isn't uncommon, there are countless examples in the standard library, e.g. http.Request, json.Encoder, json.Decoder, io.SectionReader, template.Template.
What you must ensure is that if your package returns values of your structs, they must (should) be properly initialized. And also if others are expected to pass values of your structs created by them, you must provide an easy way for them to create valid values of your structs (constructor function). Whether the custom struct values other developers create themselves are "valid", that shouldn't be of your concern.
Problem:
We know that Java doesn’t allow to extend multiple classes because it would result in the Diamond Problem where the compiler could’t decide which superclass method to use. With interface default methods the Diamond Problem were introduction in Java 8. That is, because if a class implements two interfaces, each defining the same default method, and the implementing class doesn’t override the common default method, the compiler couldn’t decide which implementation to chose.
Solution:
Java 8 requires to provide an implementation for default methods implemented by more than one interface. So if a class would implement both interfaces mentioned above, it would have to provide an implementation for the common default method. Otherwise the compiler would throw a compile time error.
Question:
Why is this solution not applicable for multiple class inheritance, by overriding common methods introduced by child class?
You didn’t understand the Diamond Problem correctly (and granted, the current state of the Wikipedia article doesn’t explain it sufficiently). As shown in this graphic,
the diamond problem occurs, when the same class is inherited multiple times through different inheritance paths. This isn’t a problem for interfaces (and never was), as they only define a contract and specifying the same contract multiple times makes no difference.
The main problem is not associated with the methods but the data of that super type. Should the instance state of A exist once or twice in that case? If once, C and B can have different, conflicting constraints on A’s instance state. Both classes might also assume to have full control over A’s state, i.e. not consider that other class having the same access level. If having two different A states, a widening conversion of a D reference to an A reference becomes ambiguous, as either A could be meant.
Interfaces don’t have these problems, as they do not carry instance data at all. They also have (almost) no accessibility issues as their methods are always public. Allowing default methods, doesn’t change this, as default methods still don’t access instance variables but operate with the interface methods only.
Of course, there is the possibility that B and C declared default methods with identical signature, causing an ambiguity that has to be resolved in D. But this is even the case, when there is no A, i.e. no “diamond” at all. So this scenario is not a correct example of the “Diamond Problem”.
Methods introduced by interfaces may always be overriden, while methods introduced by classes could be final. This is one reason why you potentially couldn't apply the same strategy for classes as you could for interfaces.
The conflict described as "diamond problem" can best be illustrated using a polymorphic call to method A.m() where the runtime type of the receiver has type D: Imagine D inherits two different methods both claiming to play the role of A.m() (one of them could be the original method A.m(), at least one of them is an override). Now, dynamic dispatch cannot decide which of the conflicting methods to invoke.
Aside: the distinction betwee the "diamond problem" and regular name clashes is particularly relevant in languages like Eiffel, where the conflict could be locally resolved for the perspective of type D, e.g., by renaming one method. This would avoid the name clash for invocations with static type D, but not for invocations with static type A.
Now, with default methods in Java 8, JLS was amended with rules that detect any such conflicts, requiring D to resolve the conflict (many different cases exist, depending on whether or not some of the types involved are classes). I.e., the diamond problem is not "solved" in Java 8, it is just avoided by rejecting any programs that would produce it.
In theory, similar rules could have been defined in Java 1 to admit multiple inheritance for classes. It's just a decision that was made early on, that the designers of Java did not want to support multiple inheritance.
The choice to admit multiple (implementation) inheritance for default methods but not for class methods is a purely pragmatic choice, not necessitated by any theory.
I understand what purpose protocols serve (to have a type conform to a set list of methods or/and properties), but I don't understand what the purpose is of a protocol with all optional methods. One example would be UITextFieldDelegate.
If all methods are optional in a protocol, why would you conform to the protocol instead of just writing the methods from scratch in your class? I don't see what the benefit or purpose of conforming to the protocol is in this case.
Are the optional methods there just as suggestions of functionality that could be implemented?
Historically, for delegates and data sources in Cocoa, informal protocols were used. Informal protocol was implemented trough a category for NSObject class:
#interface NSObject (NSTableViewDelegate)
- (int)numberOfRowsInTableView:(NSTableView *)tableView;
// ...
#end
Later, optional methods in protocols were introduced. This change leads to better documenting of class responsibilities. If you see in code, that class conforms to NSTableViewDelegate, you suspect that somewhere exists a table view, that managed by instance of this class.
Also, this change leads to stronger checks in compile time. If programmer accidentally assign wrong object to delegate or dataSource properties, compiler will warn.
But your assumption is also correct. Optional methods are also suggestions for possible functionality.
By default, all methods in a protocol are required. Each method has to be marks as optional if the nor required for everything to function correctly.
If all methods are optional in a protocol, why would you conform to the protocol instead of just writing the functions from scratch in your class?
Conforming to a protocol allow your class to tell another object the methods it has without the other object needing to know about your class. This is really useful when using Delegation as it allows the delegate to decide what information they wish to receive/provide to another class.
For example,the UIScrollViewDelegate protocol only defines optional methods. Lets say we have a class Foo that we want to know when things change with a UIScrollView.
If we decided to throw that protocol away and implement the functions from scratch, how would we tell UIScrollView which methods we implement and which methods to call when certain event occur? There is no good way it could find out. When UIScrollView was built, it didn't know about Foo so it can't know what methods it implements. Also, Foo has no way of knowing what methods can be called on it by the UIScrollView.
However, when UIScrollView was built, it did know about UIScrollViewDelegate. So if Foo conforms the the UIScrollViewDelegate protocol, there is now a common definition that both Foo and UIScrollView can follow. So Foo can implement any methods it cares about, like scrollViewDidScroll: and the UIScrollView just needs to check if the delegate implemented the methods in UIScrollViewDelegate.
The protocol establishes a contract for the interface between one object and another. The fact that the methods are optional simply says that you don't have to implement that particular method, but you can if your app calls for it.
Generally, if you're conforming to a protocol for which all of the methods are optional, though, you're doing that for a reason, namely that you plan on implementing one or more of those methods. Just because all of the protocol's methods are optional doesn't mean you will not implement any of them, but rather simply that you can elect which are relevant in your particular situation.
For example, consider the UITextFieldDelegate protocol. You'd generally conform to that because you want to specify, for example, whether certain characters should be allowed to be inserted into the text field or what to do when the return key is pressed. Sometimes you only want to implement the former. Sometimes you only want to implement the latter. Sometimes you do both. But just because you choose to implement one or the other doesn't mean you necessarily want to do other one (but you can if you want). Frankly, though, if you really didn't want to implement any of the methods, you probably wouldn't even bother to specify the delegate of the text field, nor bother to specify that you're conforming to the protocol.
Bottom line, the protocol that consists solely of optional methods basically says "if you need it, this is the documented interface for the methods you may elect to implement". The protocol still is very useful to establish the possible interfaces, but doesn't force you to implement those methods you do not need.
I am currently working on implementing multiple events which share common properties and are basically the same: Templates. Our event provider applies several events like SomeTemplateAddedEvent and SomeOtherTemplateAddedEvent. There could possibly come more variations later, so I was thinking about implementing a base class for each TemplateAddedEvent since they all share common properties. But I am doubtful if this is the right way to go, since some people prefer events to be simple classes containing every property instead of having to dig deeper to find out what the event can provide.
I hope someone can shed some light on this subject.
Inheritance is normally used for two orthogonal reasons - to reuse functionality and to declare an "is-a" relationship between classes. It seems that you're using it for the first reason. This reason is a weaker argument because reuse can also be attained with composition. The question to ask then is whether there exists an "is-a" relationship between the events. Sometimes inheritance among events is desirable, such as when it makes sense to provide a handler for all events deriving from the base class.
Overall, I'd caution against inheritance if it is only applied to attain code reuse. If it is an appropriate statement about the domain, then it can make sense.
I would like to code a proxy that forwards method invocations to another object over TCP without NSConnection and NSDistanceObject stuff. What I want is my own protocol.
The problem is that subclassing NSProxy and overriding forwardInvocation: is not sufficient. I have also to override methodSignatureForSelector
Here is my question:
– (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return ???
}
#Brian, This may be ok, but setProtocolForProxy: is just for optimization. cocoafan could mandate it for his solution, but it wouldn't be a drop-in replacement. You're supposed to be able to get signatures automatically. To do that, the network protocol needs a way to request the signature.
I believe the solution here is to include in the network protocol a "request method signature" method, and have it run methodSignatureForSelector: on the distant object and encode and return the result. That's what NSDistantObject does.
Providing setProtocolForProxy: is an important optimization if you're going to chatter a lot, but it does restrict you to objects that you have a protocol for, and prior to 10.5 that introduces some annoying limitations (all methods are required). Even on 10.5, it may introduce some problematic limitations if it's the only way to get method signatures.
#cocoafan, I think you're probably right to create this from scratch on top of NSProxy, but do take a look at NSConnection and see if you can sub-class it to manage the network connection the way you want. If you can find a way to do that (though I don't see an easy way right off), you'll probably get a lot of stuff for free from NSDistantObject.
The way NSDistantObject handles this is by its setProtocolForProxy: method, which specifies a protocol containing the list of methods that the object on the other end of the connection handles. It can then use the information for these methods to provide appropriate NSMethodSignature objects when doing forwarding.
It looks like the most straightforward to do that is via the protocol_getMethodDescription() function, declared in <objc/runtime.h>. This returns an objc_method_description struct which contains a types field. I believe you should be able to pass that value into +[NSMethodSignature signatureWithObjCTypes:] to get a method signature object that matches what's declared in the protocol.
I found a smart solution to generate NSInvocation objects.