If I subclass a class, can I specify a certain subclass an instance variable should be?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



If I subclass a class, can I specify a certain subclass an instance variable should be?



I have an NSObject subclass, BaseClass. BaseClass is a placeholder class for a couple subclasses, SubClassA and SubClassB. There is an instance variable that I have present on both of the subclasses. They're the same name, and are both of a corresponding subclass of another object. They're often used in very similar ways, so I wanted to move some functionality from my SubClassA and SubClassB to the BaseClass. However, I need access to that variable.


BaseClass


SubClassA


SubClassB



If I move the variable into the BaseClass, I am unable to specify the proper subclass of it in SubClassA and SubClassB, saying I can't override it. If I use the common parent class of this instance variable in the BaseClass, I lose some access to things that aren't common between how SubClassA and SubClassB work.


BaseClass


SubClassA


SubClassB


BaseClass


SubClassA


SubClassB



This is a more primitive example, but the basics of what I'm trying to do. This example obviously does not work. Are my only options to choose having to define common functionality within SubClassA and SubClassB or is there a proper way to achieve my goal here?


SubClassA


SubClassB


class BaseClass: NSObject
var myObject: MyObject


class SubClassA: BaseClass
override var myObject: MyObjectA


class SubClassB: BaseClass
override var myObject: MyObjectB


class MyObject: NSObject

class MyObjectA: MyObject

class MyObjectB: MyObject



This gives me the error:



Property 'myObject' with type 'MyObjectA' cannot override a property with type 'MyObject'





I really appreciate the multitude of different answer that solve this problem. Without knowing terminology, it was difficult to search for what I was trying to do. It's cool to see so many different possible methods to do this, and I've got some more guided research to be doing now than the blind google searching I was before. I wish I could select multiple right answers.
– Jake T.
Aug 10 at 21:21





I think you should identify the problem first. What you’re trying to do is called co-variance & contra-variance. Changing a Type in subclass sometimes is possible, sometimes it’s not. If it’s exactly like your example, there are two options: 1. Either your design has flaws and you’re not following the Linkskov protocol, or 2. You should use generics
– farzadshbfn
Aug 11 at 5:06





3 Answers
3



How about using generic? For simplicity, I removed NSObject


class MyObject



class MyObjectA: MyObject



class MyObjectB: MyObject



class BaseClass<T> where T : MyObject
var myObject: T?


class SubClassA: BaseClass<MyObjectA>


class SubClassB: BaseClass<MyObjectB>





Ahh, this looks like what I was looking for! I often forget generics exist, have yet to put them into practice too much. Seems like as good a time to learn as any, other than a few years ago. I'll try it out and mark this as correct when it works.
– Jake T.
Aug 10 at 20:46






@JakeT. I hope it can help. There are also other technics about subclassing. I would like to advertise my article : ).
– ukim
Aug 10 at 20:52





The one hiccup was that I separate my delegate methods into extensions, and @objc does not currently support extensions of generics (or subclasses of generics). The fix was just moving those delegate methods into the original definition. class BaseClass<T>: NSObject, DelegateProtocol where T:ServiceViewController { is the format, for anyone wondering.
– Jake T.
Aug 10 at 21:10


class BaseClass<T>: NSObject, DelegateProtocol where T:ServiceViewController {



Instead of putting the myObject related code into BaseClass, you could put it into a protocol extension. Consider this:


myObject


BaseClass


class BaseClass


class SubClassA: BaseClass, HasMyObject
var myObject: MyObjectA


class SubClassB: BaseClass
var myObject: MyObjectB


class MyObject

class MyObjectA: MyObject

class MyObjectB: MyObject

protocol HasMyObject
associatedtype MyObjectClass

var myObject: MyObjectClass get set



This is conceptually very similar to using generics, but would separate your myObject related code from the rest of the code in your class. Whether this is actually preferable over generics depends on your coding style and specific use-cases.


myObject





Hmmm, I like the look of this more, but it would require more rework than the accepted answer. If I was starting from scratch, I'd probably go this route, as it is, the generic was pretty quick to implement
– Jake T.
Aug 10 at 21:11



You can create a class function in your BaseClass that returns a class that inherits from a BaseObject (myObject) and override it for whichever class you need.


BaseClass


BaseObject


class BaseClassObject: NSObject



class BaseClass: NSObject
func generateClass() -> NSObject
return BaseClassObject()



class BranchedObject: BaseClassObject



class SubClassA: BaseClass

var myObject: NSObject?

override func generateClass() -> NSObject
return BranchedObject()


override init()
super.init()
self.myObject = self.generateClass()








By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard