Hi! I have some kind of misunderstanding protocols idea, and I hope I will find some new ideas/views on my problem here.
What is the problem? I wanted to implement Observer pattern and major target was to avoid having generics in classes which implement Observer protocol (which means, neither Observer nor Subject types should not have any associated types.). But I have ran into limitations from the language side.
How I implemented it: I've defined two protocols:
SubjectEvent protocol represents occurred event. It is an empty protocol.
Observer protocol processes events passed from the subject. It has only one method update(Subject, SubjectEvent).
Subject protocol represents a type which produces events. It has three methods: attach, detach and notify(SubjectEvent).
And now I want to have default implementation of the Subject protocol, which will store all my observers inside Set. First I thought: "Ok, I will create an extension to the Subject and provide default implementations for the methods inside". But I need get the container object (Set) from somewhere. I can define it inside Subject protocol, but that means:
This property provides to all users of this type information how it works (e.g. stores observers inside Set object).
It restricts all types which can act as Subject to store their observers inside Set.
It allows users to set observers directly through this property (not sure if this so major problem, because we have didSet observer on properties).
This leads to my current solution to use default implementation which I called SubjectBox and it keeps all this logic with storing observers inside Set. But this also leads to the problem that now I have to instantiate SubjectBox object each time I want this implementation instead of just pointing that this class implements Subject protocol.
My question is how to overcome such situations? Is my design wrong? Are there any better approaches including replacing observers with some other types, but keeping same idea of low coupling two parts of the system (e.g. model and view in classic MVC)?
If I am not mistaken, you can't extend a protocol (or anything else, for that matter) by adding a stored property in the extension. So, you can't add the Set to to extend the Subject protocol, if I understand the documentation right.
I'm not sure what you mean by "creating this type?" The type, SubjectBox, has been created. All you need do is create instances of the type to use the algorithms. You can instantiate the type in something like "var Subject1 : SubjectBox" anytime you want. You can also define other classes/types like SubjectBox2 which uses an Array, or a Dictionary, or anything else you want that implements the Subject protocol.
If I am not mistaken, you can't extend a protocol (or anything else, for that matter) by adding a stored property in the extension.
I can add it as a property inside the Subject protocol with getter and setter to modify it, then I will be able to work with this property from the extension.
I'm not sure what you mean by "creating this type?" The type, SubjectBox, has been created. All you need do is create instances of the type to use the algorithms.
I want to do not have SubjectBox type at all. Instead, I want place all this logic inside the protocol extension. Edited. Regarding "creating this type", my bad, I wanted to use instantiate. Thanks for pointing this out.
Maybe, an example will be more clear. There is the what I want to achieve:
class A : Subject {
struct WorkDoneEvent : SubjectEvent {
}
func doSmth() {
// do some work
notify(about: WorkDoneEvent())
}
}
class B : Observer {
func update(in subject: Subject, event: SubjectEvent) {
// process event
}
}
But with current approach, in class A now I should write next (additionally to the code above):