Swift refers to several languages, adding generics as a mechanism that makes people love and hate.
Generics increase the expressiveness of the language and reduce redundancy, which is good news, but the bad news is: For complex implementations, seven around eight do not revolve, the syntax is easy to stun people ... Here's one example.
This is a simplified example from my actual project. Children's shoes see the following code may ask, such a simple question, why do you have to write such a complicated implementation of the loop ... This is not said before, because the actual project complex ... This is only simplified to explain this topic, so if you are not, please forgive me.
Here is a generic protocol and another main protocol, the main agreement follows the general protocol:
Protocol Commondelegate {
associatedtype Item
func invoke (with Item:item)
}
protocol maindelegate: commondelegate {
func save (with Item:item)
}
What's strange here is the item type, what it is. It is the actual model to operate.
Since the above protocol and the compliance class are in the framework, and the actual model is in app, it is necessary to write a model agreement:
Protocol foodelegate{
var name:string {get Set}
var id:int {get Set}
var desc:string {get}
}
Remember, the actual Foo data Model class is in app, and it adheres to the Foodelegate protocol:
Class foo:foodelegate{
var name:string var
id:int var
desc:string{return
"\ (name): \ (ID)"
}
Init (name:string,id:int) {
self.name = name
self.id = ID
}
}
The next turn to the "transition" class main appeared:
Class main{
var delegate:maindelegate!
Func breed () {let
Newfoo = Foo (name: "Hopy", Id:1)
self.delegate.save (With:newfoo)
}
}
Yes, it has only one breed method, and it calls the delegate's Save method. Here is very interesting, in fact, it does not do what the work, specifically what still have to entrust delegate the final decision.
It's written right ... Wrong...
Back to the Maindelegate protocol look, it inherits from Commondelegate, which has an associated type item, you must determine the type of the item when declaring the delegate variable delegate, but here is nothing to say white ...
So we need to modify the main class into the following form:
Class main<t> where t:maindelegate,t.item:foodelegate{
var delegate:t!
Func breed () {let
Newfoo = Foo (name: "Hopy", Id:1)
self.delegate.save (With:newfoo) //todo: note This line
}
}
Notice that we have a generic t bound in Main, which determines the type of item is foodelegate. The type of item here why not foo ... Because the previous said the actual model in the app by the user defined, it can be a CoreData object or something else, the framework is not control, and do not mind these, no matter what the actual data model, as long as the observance of the foodelegate on the line.
Do you see the top todo? Don't worry, we'll say it at last.
OK, now only the last one of the actual "work" class, call it maker:
Class Maker:maindelegate {
Typealias Item = Foo
var main:main<maker>!
Func didload () {
main = main<maker> ()
main.delegate = self
main.breed ()
}
func Invoke ( With Item:item) {
print ("Invoke item:\ (ITEM.DESC) Done!!!")
}
Func Save (with Item:item) {
print ("Save Item [\ (ITEM.DESC)] done!!!")
}
}
Because obviously maker is in app, so we bind item and foo; it's not actually possible to bind to foodelegate, because non-entity types and association types cannot be bound.
The main attribute in maker is interesting, and it sets the generic type of main to itself.
The above code can be in the Xcode playground happy to play, we can actually run the next try.
If you're not dizzy here, then finally we'll talk about the Todo line ahead.
If you try to run it as I say, you'll be disappointed: there's an error in the TODO line:
For woollen. The parameter type of the Save method in the protocol is item, the actual item type is foodelegate, you may want to do a strong turn:
Let Newfoo = Foo (name: "Hopy", id:1) as Foodelegate
It's a pity that the mistake remains. We can not set the item to Foodelegate in the maker, for the reason stated earlier. So how do you write here?
Very simple, you are not to abstract. I will give you abstract:
Let Newfoo = Foo (name: "Hopy", Id:1) as! T.item
Now run OK:
This is the swift generics toss, thanks for watching.