Is there a way to know that method is protocol implementation in Swift? - swift

For example, I have such a protocol
public protocol MyProtocol
{
func foo()
}
Protocol implementation
class MyClass : MyProtocol
{
public func foo() {...}
}
there is no way to know if the method foo() is a (direct) class method or protocol implementation
So, sometimes (eg:) if a certain class implements few protocols where each of them has few methods it is hard to know which method related to which protocol.
So the question is - is there actually no way to know it?
UPD
I need to know it just for a better understanding of the code and in addition, it is easier to navigate when I know which method related to which protocol.

When you are writing code, it is usually a good idea to write implementations of protocol methods in their own separate extensions. For example:
class MyClass {
// implement methods unrelated to any protocols here
}
extension MyClass : Protocol1 {
// implement the methods in Protocol1
}
extension MyClass : Protocol2 {
// implement the methods in Protocol2
}
// etc
This way you know exactly what methods belong to which protocol.
However, let's say you are reading someone else's code that you can't change.
In Xcode, you can see if a method in a class implements a protocol by holding the command key and then clicking on its name, then the "quick actions" menu comes up:
If you click on "Jump to definition",
you will be taken to the method declaration in the protocol, if the method implements a method declared in a protocol, or
you will stay where you are, if it's just a regular old method
Do note that you will also stay where you are, if the method implements a protocol method, but is overridden. So if you see an overridden method, and wants to know if it is a requirement for a protocol or not, you'll have to go to the superclass first.
Or, use AppCode, where there are markers beside these methods:
The "I" markers with a red upwards arrow are what you're looking for. Clicking on them takes you to the declaration in the protocol. For overridden methods, they look no different from regular overridden methods, and you still need to go to the superclass first by clicking on the "O" marker with a red upwards arrow.
The only downside of this is of course, you need to pay for AppCode :(

Related

In swift, why can't I instantiate a protocol when it has an initialiser?

I understand that generally I cannot instantiate a protocol.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
My code is as below and line:
protocol Solution {
var answer: String { get }
}
protocol Problem {
var pose: String { get }
}
protocol SolvableProblem: Problem {
func solve() -> Solution?
}
protocol ProblemGenerator {
func next() -> SolvableProblem
}
protocol Puzzle {
var problem: Problem { get }
var solution: Solution { get }
init(problem: Problem, solution: Solution)
}
protocol PuzzleGenerator {
func next() -> Puzzle
}
protocol FindBySolvePuzzleGenerator: PuzzleGenerator {
var problemGenerator: ProblemGenerator { get }
}
extension FindBySolvePuzzleGenerator {
func next() -> Puzzle {
while true {
let problem = problemGenerator.next()
if let solution = problem.solve() {
return Puzzle(problem: problem, solution: solution)
}
}
}
}
The line:
return Puzzle(problem: problem, solution: solution)
gives error: Protocol type 'Puzzle' cannot be instantiated
Imagine protocols are adjectives. Movable says you can move it, Red says it has color = "red"... but they don't say what it is. You need a noun. A Red, Movable Car. You can instantiate a Car, even when low on details. You cannot instantiate a Red.
But if I include an initialiser in the protocol then surely the compiler knows that when the protocol is used by a struct or class later, it will have an init which it can use?
Protocols must be adopted by classes, and there might be a dozen different classes that all adopt your Puzzle protocol. The compiler has no idea which of those classes to instantiate.
Protocols give us the power to compose interfaces without the complexity of multiple inheritance. In a multiple inheritance language like C++, you have to deal with the fact that a single class D might inherit from two other classes, B and C, and those two classes might happen to have methods or instance variables with the same name. If they both have a methodA(), and B::methodA() and C::methodA() are different, which one do you use when someone call's D's inherited methodA()? Worse, what if B and C are both derived from a common base class A? Protocols avoid a lot of that by not being directly instantiable, while still providing the interface polymorphism that makes multiple inheritance attractive.
I understand that I can't do it - I just want to understand why the
compiler can't do it?
Because protocols in Swift represent abstraction mechanism. When it comes to abstraction, you could think about it as a template, we don't have to care about the details of how it behaves or what's its properties; Thus it makes no sense to be able to create an object from it.
As a real world example, consider that I just said "Table" (as an abstracted level), I would be pretty sure that you would understand what I am talking about! nevertheless we are not mentioning details about it (such as its material or how many legs it has...); At some point if I said "create a table for me" (instantiate an object) you have the ask me about specs! and that's why the complier won't let you create object directly from a protocol. That's the point of making things to be abstracted.
Also, checking: Why can't an object of abstract class be created? might be helpful.
Unfortunately swift does not allow that even with such "hack"
You would need to use a class that confirms to that protocol as an object you refer to.
When you instantiate an object, the Operating System has to know how to allocate and deal with that kind of object in the memory: Is it a reference type (Classes)? Strong, weak or unowned reference? Or is it a value type (Structs, Strings, Int, etc)?
Reference types are stored in the Heap, while value types live in the Stack. Here is a thorough explanation of the difference between the two.
Only Reference and Value types (objects) can be instantiated. So, only the objects that conform to that protocol can then be instantiated, not the protocol itself. A protocol is not an object, it is a general description or schema of a certain behavior of objects.
As to Initialization, here what the Apple docs say:
Initialization is the process of preparing an instance of a class,
structure, or enumeration for use. This process involves setting an
initial value for each stored property on that instance and performing
any other setup or initialization that is required before the new
instance is ready for use.

Why can't extensions with protocol conformances have a specific access level?

Assume we have the following example code:
protocol MyProtocol {
func someFunction()
}
public class MyClass {
}
public extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
Compiling the code above gives the following error:
Error: 'public' modifier cannot be used with extensions that declare protocol conformances
The same thing occurs if I mark the extension as private. It seems as though you cannot set the access level of an extension that conforms to a protocol, regardless of what the access level is set to. Even setting the protocol declaration to public or private does not remove the error.
Question
What is the reasoning for Swift restricting an extension's access level in this way if it conforms to a protocol? If the protocol conformance is applied at the class level, there is no such restriction.
If I obey the compiler and remove the private/public designation, what is the access level of someFunction()?
extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
I imagine in this case it would follow the original MyClass implementation and be public but I am not sure.
Is this behavior there because a protocol conformance in an extension means the entire class conforms to the protocol, and therefore it is redundant to re-specify the access level in the extension?
It's because it's impossible to conform to a protocol at any access level other than the access level of the protocol itself. In other words, if you have a public protocol, you cannot have private conformance to it. This is partially because protocol conformance is something that can be queried for at runtime (and therefore cannot differ between what module you're in, or be implemented twice in different files/modules), and partially because it would just plain be weird if a type conformed to a protocol in one file and didn't conform to that protocol when used in other files.
As for your question of the access level of someFunction, it follows the same rules as any other function. Which is to say, it defaults to internal, unless the type itself has a lower access level. So in your case, if MyClass and MyProtocol are both public, you can expect to get a compiler error telling you that someFunction() needs to be marked public as well. But since it looks like MyProtocol is in fact internal, omitting any access modifier works as someFunction() defaults to internal.
Private conformance might violate Liskov Substitution Principle
Quoting an abstract from apple devloper forum reply to a similar question:
"The biggest thing I've noted about private conformance, especially amonst classes that are meant to be subclassed further, is that you often end up with conflicting implementations."
For example, you have a class that privately conforms to a protocol and implements all of its methods. Later a subclass comes along and wants to do the same, but only wants to implement the required methods (because the optional ones not being implemented might provide some default behavior that subclass wants). But now you have 2 problems:
1) The object expecting this protocol implementation now has possibly 2 consumers of the protocol on the same object. This leads to both objects having to guard against unexpected calls. Or none, as due to the private conformance, the subclass can't call super to resolve the unexpected calls.
2) There is no way for the subclass to get the behavior it wants without modifying the protocol, as the superclass's implementation can't be removed without affecting its behavior either.
Source: Link to Apple Developer forum thread
If I obey the compiler and remove the private/public designation, what is the access level of someFunction()?
Whatever you say it is. Nothing stops you from marking the access level of someFunction(). But in this case you cannot mark it as private, because the access level of MyProtocol is internal.
The default, therefore, is internal in your code. Nothing is ever public by default; public is always an explicitly opt-in designation.

There is a code involves the Delegate Up, I hope I understand it right

Delegation is a new concept for me. To my understanding, it asks someone else to do some job for me. I then, delegate some tasks to him.
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
class Bicycle: Vehicle {
override init() {
super.init() //# Delegate up
numberOfWheels = 2
}
}
The code super.init() is a delegate up action in class initialization. The subclass initializer calls the initializer of the superclass first. The superclass' default initializer assigning the integer 0 to the variable numberOfWheels. This is Phase one initialization. After that, the overriding action of the subclass' initializer further customizes the variable by numberOfWheels = 2.
Question Is there any incorrectness of my understanding? and I hope the delegate up description I'm used here is correct.
Please correct any error and misunderstandings I have it here. Thanks
What you are depicting here has nothing to do with delegation-pattern at all, it's the concept of inheritance. Your bicycle class is inheriting from Vehicle. Vehicle has already implemented some code, so instead of writing it again you can use the code of the super-class (the class that is inherited from). Your super-class doesn't have a defined initializer, therefore the super.init() wont even do anything. You should read about inheritance and try to understand this concept better.
Here's what delegation does: You are right about the idea of delegation. It allows you to "outsource" some work to another class. This can be achieved with protocols. A delegate has to conform a delegation protocol to ensure that it has the methods you want to call on it. You are using protocols instead of inherited classes here, because you don't care about the implementation of the specific methods, you just want to tell your delegate to handle a situation, it's up to the delegate to know what to do.
Delegation is most commonly used in MVC applications for macOS and iOS. You can read more about delegation in the Apple Documentation. There are also dozens of tutorials like this one on the internet that show how delegation works in practice.

Swift Complex type in parameter

In order to be a bit more clear I am looking for a solution for the user to pass a class with a specific subclass and protocol, i.e. a class that inherits a viewController and delegate protocol. I know its possible to create a protocol list but cannot find a solution that works correctly. Currently I use a initializer and use the viewcontroller as a parameter and check for delegate inside the function but I would rather if I can have these types in the parameter instead.
EDIT:
Looking to do something similar to this
Protocol prot:Delegate{}
class cla:ViewController{}
class impl{
init(mainUI: cla, prot){
do things
}
}
That way back in the main view controller I can do something like this
class viewController: cla, prot{
var view:impl
override func loadView() {
//Attach to Screen
view = impl(mainUI: self);
}
}
Their is a bit more happening but that's the only part thats really relevant. Currently I use a initializer to just fail if the class doesn't inherit the correct protocols
You could create a dummy type that represents your requirements. A typealias doesn't work in this case, but this might:
class DummyClass: MyViewController, MyDelegateProtocol {}
func needsRequiredClass(input: DummyClass) {...}
With MyViewController and MyDelegateProtocol being the superclass and delegate you mentioned. The DummyClass would have an empty implementation.
Then, make your specific classes sub classes of DummyClass:
class TestClass: DummyClass {...}
And you can pass in that new class:
let test = TestClass()
self.needsRequiredClass(test)
You're asking the wrong question. In other words trying to shoe-horn in a serious design mistake.
A view should not know that its delegate is a UIViewController or a subclass.
A delegate should be any class that obeys (adopts) a specific delegate protocol.
A view should only delegate specific responsibilities. Each of those responsibilities must be described by a protocol method or property.
If you explain what your issue is in more detail (why you think you need direct access to the entire definition of a UIViewController within a UIView), we can help you avoid this mistake.

Swift and using class extension

I don't understand why programmers use the extension keyword in their class implementation. You can read in other topics that code is then more semantically separated and etc. But when I work with my own code, it feels clearer to me to use // MARK - Something. Then when you use methods list (ctrl+6) in Xcode, everything is seen at first look.
In Apple documentation you can read:
“Extensions add new functionality to an existing class, structure, or enumeration type.”
So why not write my own code directly inside my own class? Unlike when I want to extend functionality of some foreign class, like NSURLSession or Dictionary, where you have to use extensions.
Mattt Thompson use extension in his Alamofire library, maybe he can give me little explanation, why he chose this approach.
For me it seems completely reasonable since you can use extensions to expose different parts of logic to different extensions. This can also be used to make class conformance to protocols more readable, for instance
class ViewController: UIViewController {
...
}
extension ViewController: UITableViewDelegate {
...
}
extension ViewController: UITableViewDataSource {
...
}
extension ViewController: UITextFieldDelegate {
...
}
Protocol methods are separated in different extensions for clarity, this seems to be far better to read than lets say:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {}
So, I'd say there's no harm in using extensions to make your own code more readable, not just to extend already existing classes from SDK. Using extensions you can avoid having huge chunks of code in your controllers and split functionality into easily readable parts, so there's no disadvantage of using those.
Using extensions allows you to keep your declaration of protocol conformance next to the methods that implement that protocol.
If there were no extensions, imagine declaring your type as:
struct Queue<T>: SequenceType, ArrayLiteralConvertible, Equatable, Printable, Deflectable, VariousOtherables {
// lotsa code...
// and here we find the implementation of ArrayLiteralConvertible
/// Create an instance containing `elements`.
init(arrayLiteral elements: T…) {
etc
}
}
Contrast this with using extensions, where you bundle together the implementation of the protocols with those specific methods that implement it:
struct Queue<T> {
// here go the basics of queue - the essential member variables,
// maybe the enqueue and dequeue methods
}
extension SequenceType {
// here go just the specifics of what you need for a sequence type
typealias Generator = GeneratorOf<T>
func generate() -> Generator {
return GeneratorOf {
// etc.
}
}
}
extension Queue: ArrayLiteralConvertible {
init(arrayLiteral elements: T...) {
// etc.
}
}
Yes, you can mark your protocol implementations with // MARK (and bear in mind, you can combine both techniques), but you would still be split across the top of the file, where the declaration of protocol support would be, and the body of the file, where your implementation is.
Also, bear in mind if you’re implementing a protocol, you will get helpful (if slightly verbose) feedback from the IDE as you go, telling you what you’ve got left to implement. Using extensions to do each protocol one by one makes it (for me) far easier than doing it all in one go (or hopping back and forth from top to bottom as you add them).
Given this, it’s then natural to group other, non-protocol but related methods into extensions as well.
I actually find it frustrating occasionally when you can’t do this. For example,
extension Queue: CollectionType {
// amongst other things, subscript get:
subscript(idx: Index) -> T {
// etc
}
}
// all MutableCollectionType adds is a subscript setter
extension Queue: MutableCollectionType {
// this is not valid - you’re redeclaring subscript(Index)
subscript(idx: Int) -> T {
// and this is not valid - you must declare
// a get when you declare a set
set(val) {
// etc
}
}
}
So you have to implement both within the same extension.