dev_ios999
dev_ios999

Reputation: 359

Passing a generic type to a function with generic constraint

I have a protocol with an associated Type

protocol ProtocolA {
  associatedType someType
}

Now i have two generic functions

func funcA<someType>(_ data:someType) {
    funcB(data) // cannot call
}

func funcB<someType:ProtocolA>(_ data:someType) {

}

I have been trying to call funcB from funcA, but it is not working I am getting the error

Instance method 'funcB' requires that 'someType' conform to 'ProtocolA'

Now i know for a fact that the Generic Type in funcA is conforming to ProtocolA. Is there anyway to also make sure that the compilers know it too ?

I cannot change the funcA method declaration to put a generic constraint as it is the requirement of another protocol.

I have tried using the some keyword in funcA by doing

var obj : some ProtocolA = data

However i am getting the error

Property declares an opaque return type, but cannot infer the underlying type from its initializer expression

Basically in short is there anyway i can call funcB from funcA without changing funcA signature, however funcB signature can be changed to whatever is required

****EDIT*****Added More Information

funcA is called by the protocl

protocol CommonService {
    func funcA<ModelType>(_ data:ModelType)
}

class CommonServiceImpl : CommonService {
    func funcA<someType>(_ data:someType) {
        funcB(data) // cannot call
    }

    func funcB<someType:ProtocolA>(_ data:someType) {
        //SomeCode here required that someType must implement ProtocolA
    }
}

ProtocolA is contained in a third party pod that cannot be changed.

*******Edit***********How i solved the problem

So thanks to @Mojtaba Hosseini in answers i got a really good idea on how to solve my problem.

I simply wrote an overloaded function in my CommonServiceProtocol

protocol CommonService {
    func funcA<ModelType>(_ data:ModelType)
    func funcA<ModelType>(_ data:ModelType) where ModelType:ProtocolA
}

class CommonServiceImpl : CommonService {
    func funcA<someType>(_ data:someType) {
        funcB(data) // cannot call
    }

    func funcA<someType>(_ data:someType) where ModelType:ProtocolA {
        funcB(data) // can be called
    }

    func funcB<someType:ProtocolA>(_ data:someType) {
        //SomeCode here required that someType must implement ProtocolA
    }
}

I mean it is not a perfect solution but given the hard dependency on an associatedType using ProtocolA in a third party pod i would say it works alright and that is one of the reasons to avoid third party dependencies as much as possible.

Upvotes: 0

Views: 69

Answers (3)

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119128

Is there any way to also make sure that the compilers know it too?

You have to implement an overload for the funcA and constraint it:

func funcA<someType>(_ data: someType) {
    /* funcB(data) */ cannot call
    print("Not detected")

}

func funcA<someType>(_ data: someType) where someType: ProtocolA {
    funcB(data) // can call ✅
    print("Detected")
}

so calling funcA("") will result Not detected but conforming to the protocol and calling the same function will result in Detected

// extension String: ProtocolA { typealias someType = String } // uncomment to see
funcA("")

Upvotes: 1

Ruben Mim
Ruben Mim

Reputation: 181

In functionB just add a parameter that will tell the compiler the type you expect, if you really want to be sure the type is your protocol add a check :

func transform<T>( data : T ){
guard let  data = data as? Monster else {
        print("data is not a monster type")
        return
    }
intoMonster(Monster.self, data: data)
}

func intoMonster<T> (_ type : T.Type , data : T){
}

Upvotes: 0

Nikhil Jain
Nikhil Jain

Reputation: 648

As per your requirement, I think you can match the signature of your funcB with funcA. Refer to the code below:

func funcA<someType>(_ data:someType) {
    funcB(data) 
}

func funcB<someType>(_ data:someType) {

}

As shown in the above code, you can remove the type constraint for someType in funcB.

Upvotes: 0

Related Questions