Reputation: 1060
I have a class called Person with a property that specifies if there is a Grid object attached. There are 3 types of grid objects. 2 of them will have the exact same properties and the 3rd will have completely different ones.
What is the best type of abstraction to use so the Grid property in the Person class can accept all 3 types? By that I mean should I use an abstract class, base class, or interface? Or should I look into generics?
My thoughts are to use an abstract class, this way I can implement the properties and not have redundant code in the 2 classes that share the same properties. It will also force anyone adding new grid types to create a new class that is derived from it. I need this last part because I need to check which type of Grid object it is, using reflection, so I can add some conditional logic.
It just feels odd that the 3rd grid type will have these unnecessary properties.
Upvotes: 1
Views: 150
Reputation: 33143
My first question for you would be why the Person object needs to know about the grid - that sounds to me very much like you are allowing your domain level objects to take in external concerns - possibly ui for the grid or some sort of data storage concern.
Second question would be (as everyone else says) is there really any cause for abstraction with these three concepts of grid? Sounds like they are very different things.
That said, the two patterns I would look at if I were you would be Visitor and Strategy.
Both these patterns will allow you to abstract away the concrete implementation details of the grids and their relation to the Person.
Upvotes: 0
Reputation: 4928
I can't help but think that you've got bigger problems here. Suppose it's possible to have a Person object that can contain one of two entirely different objects. All of your code will read like this:
if (grid is GridTypeA) {
// do some stuff with type a
} else {
// do some stuff with type b
}
That's precisely the kind of switching on types that object orientation is supposed to eliminate. I'd look at the larger design and see if I could improve that. For instance, why does a Person class contain a Grid pointer? Speaking as a person - presumably what you're trying to model - I don't have a grid.
Upvotes: 0
Reputation: 62246
Don't know why you need to use reflection to get a type of the grid. If you write something like this, a pseudocode:
public abstract class BaseGrid {
...
...
public abstract Type GetGridType();
}
public class Grid1 : BaseGrid {
...
...
public override Type GetGridType() {
return typeof(Grid1 );
}
}
public class Grid2 : BaseGrid {
...
...
public override Type GetGridType() {
return typeof(Grid2 );
}
}
You have a GetGridType()
and don't need a relfection. The return value of that function can be any identifier you prefer based on your app design, not obviously Type.
Regards.
Upvotes: 0
Reputation: 14783
If the 3rd grid type has totally different properties then how can Person accept them all in the same way? You can only 'abstract' commonalities. You are passing 2 different things to Person - so I wouldn't try to abstract them just because they are both grids.
Upvotes: 4
Reputation: 38825
I would define an interface, which would be common to all 3 grid types.
public interface IGrid
{
// define your Grid contract here
}
I would then create an abstract base class, which defined the things common to the first two types of Grid:
public abstract class GridBase : IGrid
{
}
And derive my two common grids from here:
public class GridTypeA : GridBase { }
public class GridTypeB : GridBase { }
Finally, my 3rd (but totally different Grid), comes from IGrid
public class ObtuseGridType : IGrid
{
}
Now, my person object just has an IGrid.
Upvotes: 1
Reputation: 68740
What's wrong with an interface that covers all three Grid types, and an abstract class that implements the interface and covers the things common to the first two?
Upvotes: 1