• Post Reply Bookmark Topic Watch Topic
  • New Topic

Base class usage.  RSS feed

 
Jon Frank
Greenhorn
Posts: 5
Firefox Browser Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,
I'd love to search for existing solutions to my problem, but I really can't come up with the terminology for a search.

I think I know the answer, but I'm second-guessing myself.
In my mind, I usually create only abstract base classes to tie groups of subclasses together, never using the base class itself.

My concern is when the instantiation of heavyweight subclasses is considered prohibitively expensive, such as a large amount of member data queried from database. When that happens the database sends extraneous subclass-specific fields which are simply dropped when subclass is cast to the base class.

If I want to display a list of many items of varying subtypes of same base class, can I instantiate the base class itself?
Are there drawbacks to removing the abstract modifier from a base class?


This must seem obvious, but the vast majority of the examples I saw when learning used an abstract base class, and I guessed it a best-practice, but it doesn't seem to fit here.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jon Frank wrote:Hello,
I'd love to search for existing solutions to my problem, but I really can't come up with the terminology for a search.

I think I know the answer, but I'm second-guessing myself.
In my mind, I usually create only abstract base classes to tie groups of subclasses together, never using the base class itself.

My concern is when the instantiation of heavyweight subclasses is considered prohibitively expensive,
such as a large amount of member data queried from database.


Which has only to do with your query and your use of the ResultSet, and has nothing to do with your class hierarchy.

When that happens the database sends extraneous fields which are simply dropped when subclass is cast to the base class.


No, nothing is "dropped". Casting does not change an object in any way whatsoever. It only tells the compiler and the runtime "Treat this thing, which you were previously told was a reference of type X, as if it were a reference of type Y". The object is untouched. And keep in mind, it is just a single object, and that object IS-A base class instance and IS-A subclass instance.

Finally, there is no need to cast to the base class in the first place. There's only one use case in the entire language when that would be technically necessary, and if you encounter that use case, you probably have a design flaw in the first place.


If I want to display a list of many items of varying subtypes of same base class, can I instantiate the base class itself?


Not if it's abstract. And you don't need to do that anyway. If your base class is Fruit, and you have an Apple, and Orange, and a Banana, you can just treat them all as Fruits. If you've created your type hierarchy correctly and used polymorphism correctly, things will just work, because that's what inheritance is for.

Are there drawbacks to removing the abstract modifier from a base class?


Well, yes, if it makes sense for it to be an abstract class, then it probably does NOT make sense for it to be a concrete class. Assuming you get past any compiler errors by providing some default implementations for all the methods, you now have a class that, according to your notional design, is abstract, but that you've realized contrary to that design. Your code does not reflect your design.

Additionally, if you didn't already have meaningful default implementations such that your class COULD have been concrete from a java syntax perspective--implementations that actually belonged there and made sense and did something meaningful--and you just added some dummy method bodies to shut the compiler up, you now have methods that do nothing or do something meaningless just to satisfy the compiler, when they really should be abstract.

 
Jon Frank
Greenhorn
Posts: 5
Firefox Browser Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm having trouble explaining what I mean, although I don't doubt there are some flaws in my understanding of best-practices.

To rephrase, my problems are coming from writing subclasses to match differing levels of required detail.


Let's say I have a hierarchy of Animals: Dog, Cat, Snake, Human. A Human object might contain extensive members, including biographical information.
The database has a master lookup table Animals with shared summary data, which can help to determine animal's species an populate the appropriate subclass.

I'm trying to figure out what sort of Object to map to this lookup table, it seems like it would serve as the base class to the others.

I'm also assuming that all objects are for display purposes and are immutable, having been populated at instantiation, then returned in a collection for display.

For example: If I am querying a database for a list of Animals in a room, with the intent of filtering based on an Base Class member, i.e. isWarmBlooded(), all human data would have to have been queried to instantiate the fully fleshed out Human Object.

Would I, in that situation, allow Animal to be instantiated by removing its abstract definition, and populate it based on a slimmer ResultSet?

 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
First of all, if all your subclasses do is add additional member variables and you're half treating them as Animal and half as the subclass, then you're not really using inheritance correctly.

That point aside, if you want to do something like


Then, as I said, just treat them all as Animal. You would have an abstract isWarmBlooded() method in Animal, and each subclass would implement it to return true or false appropriately. For instance, the abstract subclass Mammal would return true, and its concrete subclasses Human, Dog, and Cat would just inherit that.

Likewise, they would each override toString() appropriately for their respective displays, or you might provide some other abstract display() method that's more tied to your specific needs.



There's no need to cast to the base class--ever. And even with the slightly dodgy extra member variables, in this particular case, each subclass's display() or toString() method would make use of whichever of its own members were appropriate for display. There's no need to know if we have a Human or a Crocodile.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jon Frank wrote:
Would I, in that situation, allow Animal to be instantiated by removing its abstract definition, and populate it based on a slimmer ResultSet?


Here you're worrying too much about microoptimizing, when you should be focusing on developing a design that's clear to understand, and easy to write, read, test, debug, maintain, and enhance. Once you have that, if the sizes of these things are a legitimate concern, you can knock up some quick tests to see if it will actually be problematic. If they are, then you may need to go back and revamp your design in some more "clever" fashion to trim things down, with the understanding that that comes at the price of increased maintenance costs.
 
Jon Frank
Greenhorn
Posts: 5
Firefox Browser Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


First of all, if all your subclasses do is add additional member variables and you're half treating them as Animal and half as the subclass, then you're not really using inheritance correctly.

I agree with you there, based on what the example I'm giving you. Mammal is an obvious superclass to human, perhaps weight would have been a better criterion for my example.

My mindset in writing so far has been:
1)Cheaply get a potentially massive list of lightweight summary objects to work with,
2)display to user,
3)based on user's input, get specific objects to do the real work.


A big question from your example:
What is the return type of getSomeAnimalsFromDb(); ?

If it is an array of animals, how am I instantiating the individual abstract Animal elements?
Do i have to determine which animal type from mixed data, then instantiate accordingly?

Something like (with arraylist):









 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jon Frank wrote:

First of all, if all your subclasses do is add additional member variables and you're half treating them as Animal and half as the subclass, then you're not really using inheritance correctly.

I agree with you there, based on what the example I'm giving you. Mammal is an obvious superclass to human, perhaps weight would have been a better criterion for my example.

My mindset in writing so far has been:
1)Cheaply get a potentially massive list of lightweight summary objects to work with,
2)display to user,
3)based on user's input, get specific objects to do the real work.


Okay, that's scratching the surface of a fairly complex ORM question, with different design options available. If you use a tool such as Hibernate, there should be facilities provided to help you do that, but the decision is made in an ORM context, rather than just a simple Java class hierarchy context. Since this is "Beginning Java", and since you still seem to have some confusion about the pure Java class hierarchy part of it, I'm going to stick to that for now, and leave the ORM part of it for another thread (and probably a different respondent who is more qualified than I to discuss those issues).

A big question from your example:
What is the return type of getSomeAnimalsFromDb(); ?
If it is an array of animals, how am I instantiating the individual abstract Animal elements?


It could be an Animal[] or any Collection<Animal>.

Do i have to determine which animal type from mixed data, then instantiate accordingly?

Something like (with arraylist):



Yes, it would be something like that. There are more sophisticated approaches you could take, using reflection and perhaps a factory class, and again, an ORM tool like Hibernate can do a lot of that automatically for you, but the basic idea is, yes, that you instantiate the appropriate concrete class, populate it from the RS, and add it to the list of animals.
 
Jon Frank
Greenhorn
Posts: 5
Firefox Browser Linux Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Yes, it would be something like that. There are more sophisticated approaches you could take, using reflection and perhaps a factory class, and again, an ORM tool like Hibernate can do a lot of that automatically for you, but the basic idea is, yes, that you instantiate the appropriate concrete class, populate it from the RS, and add it to the list of animals.



Thank you very much, Jeff.

I believe the model I have in place was working, but it was my aim for efficiency that subverted my idea of how a hierarchy should work. I'll have to read more about Hibernate, as I was thinking it was just a quick way to map objects from tables. apparently it is much more.

I wasn't aware of reflection, and will give me something to read about over the next few days.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jon Frank wrote:

Yes, it would be something like that. There are more sophisticated approaches you could take, using reflection and perhaps a factory class, and again, an ORM tool like Hibernate can do a lot of that automatically for you, but the basic idea is, yes, that you instantiate the appropriate concrete class, populate it from the RS, and add it to the list of animals.



Thank you very much, Jeff.


You're very welcome.

I believe the model I have in place was working, but it was my aim for efficiency that subverted my idea of how a hierarchy should work. I'll have to read more about Hibernate, as I was thinking it was just a quick way to map objects from tables. apparently it is much more.


It's main purpose IS to abstract away the tedium of object-relational mapping, but unless your model is very simple, it's generally not "quick". It's a very large and complex problem space, and Hibernate addresses a good-sized chunk of it, but because the problem itself is so complex, using Hibernate (or any such tool), is going to be complex too. If you do it right though, and take the time to learn the tool and the principles behind it, it will be less painful in the long run than just writing your own SQL ad hoc.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!