mtp_mc
mtp_mc

Reputation: 31

Limiting Swift protocol with advanced where

I've run into a conceptual problem and am looking for advice. I have a base class that defines all of the common properties a given object type:

class Widget {
    var id: Int
    var type: String
}

Many of these widgets share other properties and capabilities that are easily grouped. The properties / capabilities fit nicely into protocols:

protocol WidgetryA {
    func widgetAFunc()
}

protocol WidgetryB {
    func widgetBFunc()
}

It's easy to extend the Widget class to conform to these various protocols:

extension Widget: WidgetryA {
    func widgetAFunc() { }
}

Note that Widgets may conform to multiple protocols. No problem so far! What I would like to do, and what I'm struggling with, is the following... Widgets that have a certain Widget.type value should essentially be disallowed from conforming to a given Widgetry protocol. So for example:

// this obviously doesn't work with where -- is there an alternative?
extension Widget: WidgetryA where Self.type == "foo" {
    func widgetAFunc() { }
}

Now I could do something gross and inelegant like guard()ing in protocol functions to prevent Widgets of the wrong Widget.type from making calls that they shouldn't. I feel like associated types might provide a workable path to achieving what I want, but I am struggling coming up with a construct which works. Any thoughts or advice would be appreciated!

Upvotes: 3

Views: 1590

Answers (3)

Sourabh Kumbhar
Sourabh Kumbhar

Reputation: 1054

Restrict protocols to be adopted by a specific class like this :

My Protocol: MyViewController { 
  func myMethod()
}

Upvotes: 0

Łukasz Przytuła
Łukasz Przytuła

Reputation: 575

You can do an extension of the protocol:

extension WidgetryA where Self: Foo {
    func widgetAFunc() { }
}

so this widgetAFunc will be implemented only for classes that are of Foo type and conform to WidgetryA protocol. And of course you'd have to create subclasses of Widget.

Upvotes: 1

Daniel Hall
Daniel Hall

Reputation: 13679

This isn't possible as described in Swift for a couple reasons:

  1. The Swift compiler doesn't know what the runtime values for the "type" property will be

  2. Swift's generics and protocol extensions don't support excluding / disallowing / removing methods and implementations based on constraints, nor do generic constraints support matching types that are NOT something.

However, rather than using the type string, I would suggest making the Widget "type" a protocol itself, and then add the implementations via protocol extension to only instances that are Widgets that conform to the correct type protocol(s)

Upvotes: 0

Related Questions