Swift Generic Protocol Function Parameters

Swift Generic Protocol Function Parameters

Saying <NSNumber> defines a new generic placeholder type in your performRule(value:) method, which, as you've named it NSNumber, will shadow Foundation's NSNumber class – meaning that the value: parameter is of type your generic placeholder, not Foundation's NSNumber.

If you want it so that types conforming to Rule can choose their own type for the parameter of the performRule(value:) method – then you want an associated type, not a generic placeholder.

protocol NumberCalculation {
var number : NSNumber { get set }
}

protocol Rule {

// define associated type that conforming types must satisfy
// by providing a type to replace it with
associatedtype Value
var invalidMessage : String { get set }
func performRule(value: Value) -> Bool
}

struct GreaterThanRule : Rule, NumberCalculation {

var invalidMessage: String
var number : NSNumber

init(valueMustBeGreaterThan value: NSNumber, withInvalidMessage message : String = "") {
number = value
invalidMessage = message
}

// satisfy associated type implicitly by annotating the type of the parameter
// as NSNumber – the compiler will infer that Value == NSNumber.
func performRule(value: NSNumber) -> Bool {
number.decimalValue // works
value.decimalValue // also works!
return true
}
}

How to pass generic protocol as function parameter

You must use Datatype as a generic constraint:

func set<T: Datatype>(key: String, type: T ,value: T.dataType)

Note how you also need to change the type of the value parameter to T.dataType, for this to be type safe. That is, the value you pass in must be the same type as the dataType of the type parameter.

SwifT: Generic function that gets generic protocol as parameter not working

I'm not sure why you say "the protocol only demands that Element implements CustomStringConvertible." The protocol demands that echo accept and return its Element, which may or may not be String. For example, I can implement this conforming type:

struct AnotherFoo: FooProtocol {
func echo(element: Int) -> Int { fatalError() }
}

So what should happen if I then call:

callEcho(container: AnotherFoo())

This would try to pass a string literal to a function that requires an Int.

Swift - Generic function parameter

You are creating with Fly object with Bird instance

Replace code

protocol Fly {
}

class Bird: Fly {
}

func fetch<T: Fly>(model: T) {
print("Done")
}

let bird: Bird = Bird() // Here is a problem
fetch(model: bird)

Swift: How to pass the Generic protocol as a parameter for another protocol

protocol OperationDelegate {
associatedtype T
func onOperationFinished(result:Array<T>)
func onOperationError(error: Error, errorMessage:String)
}

protocol ResultDelegate {
func findResult<OpDelegate: OperationDelegate>(query: String, odelegate: OpDelegate)
}

//Added few PlayGround works

    class ResultsFinder: ResultDelegate {

func findResult<OpDelegate>(query: String, odelegate: OpDelegate) where OpDelegate : OperationDelegate {

print(#function)
// Do some operations
let s1 = Student()
s1.name = "one"
let s2 = Student()
s2.name = "two"

let addressList = [s1,s2]
odelegate.onOperationFinished(result: addressList as! [OpDelegate.T])

}
}

also

class ResultDisplay: OperationDelegate {

typealias T = Student

func onOperationFinished(result: [Student]) {
// Display address
print(#function)
}

func onOperationError(error: Error, errorMessage: String) {
// Display error
print(#function)
}

}

class Mainfunction {

let resultDisplay = ResultDisplay()
let finder = ResultsFinder()
func start() {

print(#function)
finder.findResult(query: "Sridhar", odelegate: resultDisplay)

}

}

let main = Mainfunction()
main.start()

Difference between using Generic and Protocol as type parameters, what are the pros and cons of implement them in a function

There is actually a video from this year's WWDC about that (it was about performance of classes, structs and protocols; I don't have a link but you should be able to find it).

In your second function, where you pass a any value that conforms to that protocol, you are actually passing a container that has 24 bytes of storage for the passed value, and 16 bytes for type related information (to determine which methods to call, ergo dynamic dispatch). If the passed value is now bigger than 24 bytes in memory, the object will be allocated on the heap and the container stores a reference to that object! That is actually extremely time consuming and should certainly be avoided if possible.

In your first function, where you use a generic constraint, there is actually created another function by the compiler that explicitly performs the function's operations upon that type. (If you use this function with lots of different types, your code size may, however, increase significantly; see C++ code bloat for further reference.) However, the compiler can now statically dispatch the methods, inline the function if possible and does certainly not have to allocate any heap space. Stated in the video mentioned above, code size does not have to increase significantly as code can still be shared... so the function with generic constraint is certainly the way to go!

Make a function parameter be of a protocol type that also conforms to a protocol

You need to change your function signature to use the generic type constraint as the input argument's type and restrict the generic type parameter to be MyProtocol and CaseIterable.

func enumFunc<T: MyProtocol & CaseIterable>(_ myEnum: T.Type) {
myEnum.allCases // <--- This is what I would like to do
}

Protocol function with generic type

Status of the features needed to make this work:

  • Recursive protocol constraints (SE-0157) Implemented (Swift 4.1)
  • Arbitrary requirements in protocols (SE-0142) Implemented (Swift 4)
  • Generic Type Aliases (SE-0048) Implemented (Swift 3)

Looks like this is currently not possible without introducing boxed types (the "type erasure" technique), and is something looked at for a future version of Swift, as described by the Recursive protocol constraints and Arbitrary requirements in protocols sections of the Complete Generics Manifesto (since generic protocols are not going to be supported).

When Swift supports these two features, the following should become valid:

protocol Parser {
associatedtype Result
associatedtype SubParser: Parser where SubParser.Result == Result

func parse() -> ParserOutcome<Result, SubParser>
}

enum ParserOutcome<Result, SubParser: Parser where SubParser.Result == Result> {
case result(Result)
case parser(P)
}

With generic typealiases, the subparser type could also be extracted as:

typealias SubParser<Result> = Parser where SubParser.Result == Result


Related Topics



Leave a reply



Submit