Imagine the following scenario.
class Shape
{
// methods of Class Shape
}
class Circle extends Shape
{
// methods of Class Shape
// methods of Class Circle
}
class Square extends Shape
{
// methods of Class Shape
// methods of Class Square
}
class Canvas // This class should a bucket of objects that belong to Square and Circle
{
// Declaring a single list of supertype
List<Shape> heterogeneousCollection;
// Declaring two separate lists
List<Cirlce> homogeneousCollection;
List<Square> homogeneousCollection;
}
The corresponding relational schema is as follows
- Table Shape contains master information
- Tables Circle & Square enrich data in Shape by a way of foreign key reference (Circle & - Square are disjoint sets with different columns)
- Table Canvas is a sort of aggregation of data
- Canvas joins Circle (1..n cardinality)
- Canvas joins Square (1..n cardinality)
Which is the better approach "Declaring a single list of supertype (heterogeneous collection)" or "Declaring two separate lists (two different homogeneous collections)"
I'm considering the following points when making a decision.
- How do we populate object Canvas when reading from a database?
Consider a way of avoiding N+1 problem and reading from a single query something like
SELECT * FROM
Canvas INNER JOIN Circle ON ..
Canvas INNER JOIN Square ON ..
Circle INNER JOIN Shape ON ..
Square INNER JOIN Shape ON ..
Now, for every one record of Canvas we end up with (B+C) rows. However, with several ORM tools it is possible of group distinct data sets in Circle and Square into two separate lists. (I'm considering iBatis here)
How do we handle several functions on these objects?
Imaging a case where we are planning to handle a UI function to display data in object Canvas. Apart from common functions between Circle and Square, each of them can have different functions. For example Square can have getLengthOfSide(), whereas Circle can have getRadius(). If we use heterogeneous list, we might end up using a cast operator at every place we need access to these functions.Class Canvas { void drawAll() { for (Shape s : heterogeneousCollection) { if (s instanceof Circle) { s.draw(); // common function present in Shape also s.xyz(); // specific to Circle } if (s instanceof Square) { s.draw(); // common function present in Shape also s.abc(); // specific to Square } } } }
In case of two homogeneous list we might have two different for loops for each list separately.
However, if we need to add a new kind of shape (say triangle), it is affecting Canvas, which I feel is a result of design flaw and Java might be equipped to deal with this. Kindly throw some light on this. Any reference to books/links would be of great help. Just wanted to tell you guys that this is not a school assignment and I'm seriously looking at various solutions. Pardon me for a long question.
PS: One other solution List<? extends Shape>
is ruled out because we cannot insert any objects into this collection.