Inheritence in swift protocols - swift

How to resolve in swift (2.0) that case: we have two protocols:
protocol SuperDelegate{
func handleSuccess(rsp: BaseRsp)
}
protocol ChildOfSuperDelegate: SuperDelegate {
func handleSuccess(rsp: ChildOfBaseRsp)
}
and some place in code where we want do:
class A{
var delegate:SuperDelegate?
func foo(){
delegate?.handleSuccess(childOfBaseRspObj)
}
}
class Xyz:ChildOfSuperDelegate{
func handleSuccess(rsp: ChildOfBaseRsp){
print("Great!")
}
}
but compiler not founding inheritence in protocols (handleSuccess have function with base and child parameters) there are compile error:
Type 'Xyz' does not conform to protocol 'SuperDelegate'
. How to resolve them? What is the best way to only implements ChildOfSuperDelegate methods but class "A" use SuperDelegate variable.
Meybe I must use generic types to have somethink like inheritance in protocols.

Here your protocol ChildOfSuperDelegate is inherited from SuperDelegate and though it is a protocol it doesn't implement its methods. But when you inherit from ChildOfSuperDelegate you have to implement method of SuperDelegate as well ChildOfSuperDelegate.
So do like this:
class Xyz:ChildOfSuperDelegate{
func handleSuccess(rsp: BaseRsp) {
//do stuff
}
func handleSuccess(rsp: ChildOfBaseRsp){
print("Great!")
}
}

Related

Using Protocols Functions inside a Class

studying Protocols here and I'd like to know why that code does not print. Thanks in advance.
import Foundation
protocol PrintSomething {
func printMyname(name: String)
}
class Display {
var myProtocol: PrintSomething?
func somethingToDisplay() {
myProtocol?.printMyname(name: "Ygor")
}
}
let display = Display()
display.somethingToDisplay()
Because you never instantiated an actual instance of PrintSomething. You have a reference to an optional which defaults to nil. Are you perhaps trying to have Display conform to the protocol? You need an actual type to conform to the protocol and then instantiate that to be able to call it.
struct Printer: PrintSomething {
func printMyname(name: String) {
print(name)
}
}
class Display {
var myProtocol: PrintSomething = Printer()
func somethingToDisplay() {
myProtocol?.printMyname(name: "Ygor")
}
}
Now you have a real type (a struct) implementing the protocol, you're instantiating it so that the reference isn't nil, and then you're calling it.
You can do better, though, by having Display implement the protocol directly.
class Display: PrintSomething {
func printMyname(name: String) {
print(name)
}
}
let display = Display()
display.printMyname(name: "whatever")
You can use your code like below
protocol PrintSomething {
//declaration
func printMyname(name: String)
}
class Display: PrintSomething {
//defination
func printMyname(name: String) {
print(name)
}
var myProtocol: PrintSomething?
func somethingToDisplay() {
myProtocol?.printMyname(name: "Ygor")
}
}
And finally you can call it from any where like below
let display = Display()
display.somethingToDisplay()
You can read more about Protocol here
The documentation is pretty clear about what a protocol is:
A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.
For starters, you need an object to conform to your protocol which provides an actual implementation of the blueprint, because that is what a protocol is. Imagine you're building a house. You have the blueprint for it, but you still have to implement it in the real world.
protocol PrintSomething {
func printMyname(name: String)
}
class Display: PrintSomething {
func printMyname(name: String) {
print(name)
}
}
let display = Display()
display.printMyname(name: "My name")
If you wish to understand protocols in Swift I strongly recommend you begin with the documentation and start practicing the examples.
You have defined a property to be of a protocol type but you never assign something to that property and for that you need a concrete type, a struct or a class, to implement your protocol,
struct Example: PrintSomething {
func printMyname(name: String) {
print("This is my name: \(name)")
}
then you need to use it
let display = Display()
display.myProtocol = Example()
Now it will print when you call display.somethingToDisplay()

How do you name the functions in a Swift Protocol?

When I declare a Protocol in Swift like this, say for a network module:
Protocol MyNetworkProtocol {
func reportError(error: Int) // <-- do you add prefix for this?
}
How do you name the functions inside a protocol? Do you add prefix for it?
I ask this because if I name the function as shown above, the caller would be like:
class MyClass: MyNetworkProtocol {
// some code for MyClass
func reportError(error: Int) {
// some code to handle it
}
}
If I view the code in MyClass solely, reportError cannot be identified as a the implementation of a protocol of another class immediately (unless I add some comment in the code).
I am thinking to name the functions in protocols like this:
Protocol MyNetworkProtocol {
func myNetworkProtocol_reportError(error: Int)
}
So that in MyClass, I can quickly know it's a implementation of a protocol for a certain class. Is this necessary? Do I misunderstand some concept?
Don't do that. Instead segregate the protocol methods into a separate extension.
class MyClass {
}
extension MyClass: MyNetworkProtocol {
func reportError(error: Int) {
// some code to handle it
}
}
In protocol function start by protocol name with arguments of protocol class & additional
Protocol MyNetworkProtocol {
func myNetworkProtocol(_ myNetwork: MyNetworkProtocol, _reportErrot: Int)
}
}
Like this function will help to debug easily

Emitting a warning for a deprecated Swift protocol method in implementing types

Suppose I have a protocol with a bar() method that has a default implementation — essentially the Swift way of making a protocol requirement optional for implementing types:
protocol Foo {
func bar()
}
extension Foo {
func bar() {
print("default bar() implementaion")
}
}
Now suppose that I decide to rename that method barrrr(), because more rs are better:
protocol Foo {
func barrrr()
}
extension Foo {
func barrrr() {
print("default barrrr() implementaion")
}
}
Existing code may still implement the method with the old name:
class Thinger: Foo {
func bar() {
print("custom bar() implementaion")
}
}
This code thinks it’s customizing a Foo method, but it isn’t. Callers will look for barrrr(), and get the default implementation. Nobody calls bar().
I would therefore like to generate a warning for types that implement Foo and have a bar() method. This does not work:
protocol Foo {
func barrrr()
#available(*, deprecated: 0.99, renamed: "barrrr()")
func bar()
}
extension Foo {
func barrrr() {
print("default barrrr() implementaion")
}
func bar() {
fatalError("renamed barrrr()")
}
}
class Thinger: Foo {
func bar() { // No warning here!
print("custom bar() implementaion")
}
}
Making the extension method final has no effect. Is there a way to do it? It needn’t be a friendly warning; any compiler error would suffice.
If I understand the question correctly, I don't believe there is a way to do this--nor should there be.
You have a protocol, let's call it MyProtocol...
protocol MyProtocol {
func myOldFunction()
}
extension MyProtocol {
func myOldFunction() {
print("doing my old things")
}
}
And in a later release, you would like to rename a function within your protocol.
protocol MyProtocol {
func myOldFunction() // now deprecated
func myNewFunction()
}
The primary problem with throwing a deprecation warning on any class which conforms to MyProtocol and implemented myOldFunction() is that there's nothing wrong with classes implementing functions and properties that are not part of your protocol.
These methods or properties might still be perfectly valid implementations used by other things that don't care about your protocol.
Consider that nothing would stop us from doing this:
protocol ViewControllerDeprecations {
func viewDidLoad() // mark deprecated
func viewWillAppear(Bool) // mark deprecated
// etc., for all the life cycle methods
}
extension UIViewController: ViewControllerDeprecations {}
Now every UIViewController subclass everywhere in any app that contains the file with the above code has these silly deprecation warnings all over it just because your particular protocol no longer uses these methods.
Without taking a position on whether it is a good thing, as suggested by another answer, exactly what you are asking for is not possible at least in Swift 3.
However, as I pointed out in response to a related question, it is possible to deprecate an entire protocol, and doing so would at least give you deprecation warnings at the implementing type level, if not precisely at the wanted property / method level.

Calling protocol default implementation from regular method, when protocol has associated type

I have a protocol that has a static method with a default parameter. I want to change the default value in a class that implements the protocol. Essentially doing what is easily done with classes and super.
I only have a solution when the Protocol has no associated type.
The following code works, but as soon as you uncomment the associated type declaration, it doesn't compile.
protocol Protocol {
// associatedtype AssociatedType
}
extension Protocol {
func sayHello(name: String = "World") {
print("Hello, \(name)!")
}
}
class Class<T>: Protocol {
typealias AssociatedType = T
func sayHello(name: String = "Stack Overflow") {
// Uncommenting the Protocol.AssociatedType causes:
// Protocol can only be used as a generic constraint because it has associated type requirements
(self as Protocol).sayHello(name)
}
}
Class<()>().sayHello()
I do understand why it doesn't compile: Protocol has no concrete type for AssociatedType.
So maybe the question should read "Can I explicitly specialize a protocol?", to which I believe the answer is no.
I have a partial workaround. But even when it works, it sucks.
Especially when you consider that I'm writing a library where sayHello is public, so the following workaround forces me to have a second protocol, which has to be public, but is useless.
Here's the workaround:
protocol Parent {}
protocol Protocol: Parent {
associatedtype AssociatedType
}
extension Parent {
func sayHello(name: String = "World") {
print("Hello, \(name)!")
}
}
class Class<T>: Protocol {
typealias AssociatedType = T
func sayHello(name: String = "Stack Overflow") {
(self as Parent).sayHello(name)
}
}
Class<()>().sayHello()
But this doesn't work for me, because my sayHello uses the associated type. So it can't be extracted to another protocol.
Just to be sure I'm clear, here's what I'd like, only substituting the class for a protocol:
class Protocol<T> {
func sayHello(name: String = "World") {
print("Hello, \(name)!")
}
}
class Class<T>: Protocol<T> {
override func sayHello(name: String = "Stack Overflow") {
super.sayHello(name)
}
}
Class<()>().sayHello()
You're trying to reinvent inheritance in protocols, and there is no such thing. But it is trivial to get what you're talking about; just say what you mean. You don't mean "I want to do the thing I inherited." You mean "I want to do some common behavior." Just provide a name for that common behavior. This removes all ambiguity about which one you mean.
protocol Protocol {
associatedtype AssociatedType
}
extension Protocol {
// Put the default behavior on the protocol, not on the instance
// Of course you could also put it on the instance if that were convenient.
static func defaultSayHello(_ name: String = "World") {
print("Hello, \(name)!")
}
// If you want a default on the instance, too, provide one that we an override
func sayHello(_ name: String = "World") {
Self.defaultSayHello(name)
}
}
class Class<T>: Protocol {
typealias AssociatedType = T
func sayHello(name: String = "Stack Overflow") {
// Now the default behavior lives on my type
Class.defaultSayHello(name)
}
}
// But other types can get default behavior
class OtherClass<T>: Protocol {
typealias AssociatedType = T
}
Class<()>().sayHello() // Hello, Stack Overflow!
OtherClass<()>().sayHello() // Hello, World!
The one frustrating part about this is that Swift provides no way to limit defaultSayHello to implementers of Protocol. So technically anyone can call it. It can sometimes be worth prefixing it with an _ to indicate that outsiders shouldn't. This is a basic access control problem in protocols, having nothing to do with this specific question; it comes up all the time when you want "things my implementers can use on themselves, but shouldn't be called randomly." Swift doesn't have a solution for that today.
Inspired by Rob Napier's answer, here's what I went with; good old overloading for defaults:
protocol Protocol {
associatedtype AssociatedType
}
extension Protocol {
func sayHello(name: String = "World") {
print("Hello, \(name)!")
}
}
class Class<T>: Protocol {
typealias AssociatedType = T
func sayHello() {
self.sayHello("Stack Overflow")
}
}
Class<()>().sayHello() // Hello, Stack Overflow!
Class<()>().sayHello("you") // Hello, you!
This does fit my needs, but doesn't answer the question. So I'm not 100% satisfied.
I believe Rust gets this one right by allowing traits/protocols to be generic both using X<T> and associated types.

Swift: Generic Protocols

I have some swift structs for which protocol compliance is generated with individual extensions with equal methods names which just differ in their return types which are struct dependent. On top of That I want to use them in a generic function which Calls a protocol conforming function for a generic type).
I tried to accomplish this like that:
//: Playground - noun: a place where people can play
import UIKit
protocol FooProt {
typealias T;
static func createMe<T>()->T;
}
struct FooStruct{
}
extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe () -> FooStruct{
return FooStruct();
}
}
class Creator{
fun createOne<T where T:FooProt>(type:T.Type){
let instance = T.createMe();
}
}
Unfortunately I get the following error :
/var/folders/sn/78_zvfd15d74dzn01mdv258h0000gq/T/./lldb/3741/playground6.swift:7 :17: note: protocol requires function 'createMe()' with type ' () -> T' (aka '<τ_1_0> () -> τ_1_0')
static func createMe()->T;
What exactly doesn't comply here and is there a workaround ?
There are several problems with your code. On the one hand you have defined a protocol with an associated type. However, you define your createMe() method as a generic which uses some other type. I don't think that was your intent. I think your intent was to have a createMe() method that returns the same type as the protocol's associated type. In this case you need to remove the from the createMe() method. Also, the name createMe() implies that you aren't just returning any type, but the type of the object on which this method is being called. In this case, you don't even need an associated type protocol. You just need a protocol with a Self constraint which allows your code to be a bit simpler. In your Creator's createOne method, your type constraint is more complex than needed.
I think you want the following code:
protocol FooProt {
static func createMe()->Self;
}
struct FooStruct{
}
extension FooStruct: FooProt {
static func createMe() -> FooStruct {
return FooStruct();
}
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.createMe()
}
}
let foo = Creator().createOne(FooStruct.self)
Here is an alternate solution using an initializer in the protocol instead of a static method.
protocol FooProt {
init()
}
struct FooStruct{
}
extension FooStruct: FooProt {
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.init()
}
}
let foo = Creator().createOne(FooStruct.self)