Open itaiferber opened 8 years ago
Today the only fully general way to do this is to put requirements in Fooable that can then be satisfied by default implementations in PrimitiveFooable and StructuredFooable. In cases where there are no associated parameters and no self-requirements, you can also "get the T back out" by using an extension method:
protocol Fooable {}
protocol StructuredFooable: Fooable { /*...*/ }
extension StructuredFooable {
func doStructuredFooThing() { print("structured!") }
}
func doFoo<T>(with value: T) where T: Fooable {
if let v = value as? StructuredFooable {
// Same here
v.doStructuredFooThing()
}
}
struct StructuredFooableImpl: StructuredFooable {}
doFoo(with: StructuredFooableImpl())
Thanks for the quick response, @belkadan!
Unfortunately, PrimitiveFooable
and StructuredFooable
are disparate, so there's no requirement I can place inside Fooable
that really makes sense (what I truly need here is not Fooable
but an anonymous union type of PrimitiveFooable | StructuredFooable
, but Swift doesn't support that ATM), but I will keep exploring this.
Additional Detail from JIRA
| | | |------------------|-----------------| |Votes | 1 | |Component/s | Compiler | |Labels | New Feature, LanguageFeatureRequest | |Assignee | @itaiferber | |Priority | Medium | md5: dc8627120fe0771eeb2e6cc79ec4e5dcIssue Description:
As part of the design of an API (which we are implementing internally, but intend to also offer for third parties to implement), I have a class of things which are
Fooable
. Some things are, sayPrimitiveFooable
, while others areStructuredFooable
:What I would like to do is write a generic method which accepts all {Fooable}, but dispatches correctly on whether the parameter is
PrimitiveFooable
orStructuredFooable
:However, it seems to currently be impossible to constrain the type
T
withindoFoo
in a type-safe manner:The "right" solution might appear to be to overload the method based on type:
but in practice, this leads to an untenable number of overloads for this specific API:
must necessarily then become
The implementations of these methods would be quite similar, causing a lot of unnecessary repetition and copypasta.
Unless there's some method or syntax for doing this that I've missed, this would be an extremely helpful addition. Right now, we work around this by making
PrimitiveFooable
conform toStructuredFooable
(andfatalError()
by default on its methods), which solves the duplication problem as we only have methods which takeStructuredFooable
(and check dynamically forPrimitiveFooable
), but is not safe at all.