How to declare a var of specific base class, conforming to a protocol?

How would I declare a variable that is of a specific base class and conforms to a protocol?

For example if I have


class BaseClass { ... } 
protocol SomeProtocol { ... }


I can either declare it as

var someVar: BaseClass

or as

var someVar: SomeProtocol

but not as

var someVar: BaseClass, SomeProtocol

I also tried to declare the protocol as

protocol SomeProtocol: BaseClass

But of course this didn't work, as non-class types can't inherit from classes

In Objective-C I would do

BaseClass<SomeProtocol> *someVar;

But in Swift <> is reserved for generics.

I can do this for function parameters and it works just as expected:

func someFunc<T: BaseClass where T: protocol<SomeProtocol>>(param: T)


I could turn my protocol into a subclass of the BaseClass, but what if down the road I need some other base class, conforming to the protocol?


My concrete use case is that for a custom keyboard I have a controller that loads a bunch of different UIView subclasses (for different types of keyboards) that are constructed from different NIBs. They have custom functionality (abstracted in mini controllers of their own), but a common interface. If I declare them as variables conforming to a protocol, I would not be able to naturally use their UIView functionality without casting. I also won't get type safety when assigning/reading them. Same if I declare them as plain UIViews and cast.

Variables are instances of types. Only types can conform to protocols. So you can do this:

class SomeClass: SomeProtocol { ... }
var v = SomeClass()


The variable v will now be an instance of the type (class) SomeClass, which conforms to SomeProtocol.


You should probably read the documentation and make sure you know the basics of variables and types, classes, structs, enums, protocols, etc.

I know how to instantiate. My question is how to declare a variable, to which I can set only objects that are both of a specific base class and conform to a specific protocol.

You can't as far as I know.

Ah, I misread your question and jumped to conclusions, sorry about that.

Perhaps you can create a protocol for the common interface and extend the base class to conform to it:

EDIT: added example:

class KeyboardThingBase: UIView { ... }
class SomeKeyBoardThing:  KeyboardThingBase { ... }
class OtherKeyBoardThing: KeyboardThingBase { ... }

protocol CommonInterface {
  ...
}
extension KeyboardThingBase: CommonInterface {
  ...
}

var v: KeyboardThingBase // Things in v are subclasses of KeyboardThingBase (and UIView) and conform to CommonInterface.

Isn't it easiest to not derive from UIView, but a class you create called NameOfProtocolUIView, which implements your protocol?

I could make a class that inherits from UIView (or whatever base class I need) and conforms to the protocol and stub the methods. Then subclass it to my concrete subclasses where I actually implement the methods, but this is a rather messy solution, questioning the role of the protocol.

Because I use a protocol exactly because implementation differs in the different subclasses, it's the interface (protocol) that stays the same.


For me it is a feature omission. It is something that was there in Obj-C and had it's use cases.

Abstract classes, or at least abstract methods, would also be an improvement, but being able to use the colon+comma syntax for explicitly typing would be best, for your use case.

/.../ but this is a rather messy solution, questioning the role of the protocol


Agreed. Just to be clear, is this a correct representation of your situation:


class BaseA: UIView { ... }

class BaseB: UIView { ... }


protocol CommonInterface { ... }


class Foo: BaseA, CommonInterface { ... }

class Bar: BaseB, CommonInterface { ... }


var v: X


Where X is something that says v holds any type that conforms to CommonInterface AND is a subclass of either BaseA OR BaseB, so it can for example store Foo and/or Bar and then you want v to give you access to both the stuff in CommonInterface and the things specific to either BaseA (for Foo) or BaseB (for Bar) without casting?

How to declare a var of specific base class, conforming to a protocol?
 
 
Q