Paul
Paul

Reputation: 26680

Same properties introduced in various descendant classes

I am using Delphi, but deliberately do not want you to stick with specific language because the problem is a fundamental one.

My application contains by now a list of data records, of various types. Each record has a different set of properties. At this moment all the records are represented in RAM by objects of the same universal class. There is a field inside which represents a record type, and getters/setters lock and unlock retrieval or change of data according to this field contents.

I am planing to develop a strict architecture with polymorphism usage where each record type will be represented by a corresponding descendant class. The parent class will not contain any descendant-specific properties, but the common ones only.

Now, the problem:

Some available properties exist in several descendant classes, but should not appear in a base class. Their getters and setters are identical. How not to repeat myself and write one getter and one setter per property?

The only idea that comes to my mind is to implement all the properties in a base class as protected and then move them to public section in descendant classes.

Do you consider this solution good or bad? Why?

Are there any other ways to achieve the goal?

Illustration:

class Base
   prop A
   prop B

class Desc1:Base
   prop C
   prop D

class Desc2:Base
   prop D
   prop E

class Desc3:Base
   prop C
   prop E

Upvotes: 3

Views: 91

Answers (2)

Aliaxander
Aliaxander

Reputation: 2617

You idea is not good because by making some properties protected you enforce them to be included into all subclasses, which is obviously not correct. Moreover, if a number of subclasses grow, you'll have to include more and more properties into you base class.

What you can do instead is introduce abstraction allowed for multiple inheritance or for being mixed in:

  • (abstract) class in C++
  • interface in Java
  • trait in Scala

that will contain one of the properties C, D or E. For example:

interface CHolder
    prop C

interface DHolder
    prop D

interface EHolder
    prop E

Now you can make DescN extend the needed abstractions:

class Base
   prop A
   prop B

class Desc1:Base, CHolder, DHolder

class Desc2:Base, DHolder, EHolder

class Desc3:Base, CHolder, EHolder

Upvotes: 1

gia
gia

Reputation: 757

First, I don't know Delphi, but you claim we shouldn't take it into account. Under pure OOP, you would create a superclass that has the shared properties, but only if the child classes have a logical link between each other. eg. Dog and Cat are both Animal, Animal can have the property hasTail which is shared by Dog, Cat and usually Animal. However, Plane would not be extending Animal, despite also having the hasTail property.

However pure OOP is not always practical (for instance, if you end with an inheritance tree of depth 200). I suggest, unless there is a substantial group of shared properties, and better yet, that it makes sense to group them in a superclass. That you just bite the bullet and type the extra accessors.

If there is a substantial group of shared properties, but the classes should not be extending the same class (because Cat and Plane), you could look into interfaces. An interface defines behavior you want to expose that is shared by many classes that shouldn't be grouped by a superclass (again Cat and Plane could have Turn,Forward,SlowDown,AcceptPassengers and whatever on an interface PublicTransport). It wouldn't save you typing, but its the "proper way".

Check whether Delphi has an IDE that allows you to generate all these accessors without you doing but a few clicks. Java does. In that case you would have a file for each of these classes, now called "beans", that only have properties and automatically generated accessors. While you have more hands-on logic somewhere else if possible. That way you only edit the bean when you need to add/delete a property.

If it doesn't, and the number of shared properties is substantial, feel free to do what you want, but leave a lot of comments because whoever has to maintain that (including future you) is gonna have trouble.

You could have a single property, "properties", with a map of "propertyname"->"value". And define the property list on the constructor, with only a single generic getter and setter on the base class. But that is if you don't want the language to handle checking for you and want to be open ended about what properties you want to have.

Upvotes: 2

Related Questions