• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Paul Clapham
  • Jeanne Boyarsky
Sheriffs:
  • Junilu Lacar
  • Knute Snortum
  • Henry Wong
Saloon Keepers:
  • Ron McLeod
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Frits Walraven
  • Joe Ess
  • salvin francis

Overriding a final field

 
Ranch Hand
Posts: 92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everyone.
I have a parent class that specifies methods that utilize fields to return results. The goal is to have the fields be instantiated by child classes, but I need to be SURE they are instantiated or I could get a null pointer exception. Because sometimes the fields refer to heavy weight objects, I do not want the fields instantiated by the parent's constructor and then immediately replaced by the child's constructor. I want to make sure that every such variable is definitively initialized. Ideally I would like them to be final.

So to make this concrete lets say we are making some message parsing classes for different kinds of TCP/IP messages. For example: eMail (SMTP), time(NTP), web (HTTP), etc.



And so now we can see the problems. First, my parent class, AbstractMessageParser did not have a constructor. That means I cannot make the fields final, even though for any given parser, they may never change. That is annoying if I want to make the Parser classes immutable for some reason. So I decide to add a constructor that takes the values of these two fields as arguments. I then force child classes to pass these values to their super constructor. Even if I didn't care about finality, it is critical that all the fields used by the methods defined in the parent class are instantiated in the constructors of the child classes. I have no way to enforces this (that I know of) without the constructor.

So we have now have


This has 2 problems.
(1) a network message might have far more than 2 parameters that define it. There could many common parameters, and the constructors would get tedious. A builder pattern is the obvious solution to this problem.
(2) the call to super() in the child class, must be the first line in the constructor, but some fields that I have to pass may not have a simple construction and could not be easily built in the parameter field of the call to super. You could fix this by making the Smtp Constructor private and adding a public static factory method to the class.

You will forgive me if I forgo writing out the code possible code for the builder and the factory method patterns. As an alternative to the builder method in item #1, I could also create a set of parallel container classes (by 'container class I mean a class that has no methods) to hold the constants associated with a particular type of message. Since most of those constants would be immutable, this system would be advantageous if many instances of the parser were required. But it even more code that needs to be written for what I feel should be a rather simple problem.

So what I _want_ to be able to do is something like the following.

I want to declare all the common fields in the parent class (AbstractMessageParser),
I want to declare them to be final, but not initialize them.
I want to be forced by the compiler to initialize the final fields in the constructor of all child classes or be forced to declare the child class abstract.


Now things are much easier to write. I have one parent class that declares the common state, and a number of child classes, each of which has a host of constants that are specific to its own class, that implement that state. NO builder pattern, no parallel classes, no factory methods. Piece of cake. But it doesn't work.

Is there some way to do this sort of thing with annotations? And/or some kind of testing paradigm?

Perhaps I could put the @Override annotation on the fields, and if they hide a field in the parent class (same name and same type) then the field of the parent class would not be initialized. The point about not being initialized is important, because if the field declares an object that takes a lot of time to construct you don't want to instantiate it twice. And you certainly don't want a hidden instance of a field that you don't use taking up space (as if hidden fields weren't dangerous enough).

It really feels like there should be something for this situation. Some keyword or usage of Java syntax that I haven't learned yet. Can someone set me straight?






 
Marshal
Posts: 66949
255
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Derik Davenport wrote: . . .
Perhaps I could put the @Override annotation on the fields, . . .

No, you can't You can't override fields; the only thing you can override is non‑private non‑final instance methods. And that is it.

Don't go hiding fields; that way lies confusion and errors. The ideal is that you design your inheritance hierarchy so all classes use the same fields. You initialise fields with the constructor and you initialise superclass fields with the super(...); line in the subclass' constructor. That way you have one copy per object and there is no need to waste memory. Whoever told you that you should add fields in subclasses should be shot. And so should whoever told you to call them child classes

What makes you think your superclass has no constructor? It has a default constructor, which means whoever wrote that class made a mistake. What is wrong with the second code you wrote? You can make all the fields final, then the compiler will complain bitterly if any is not initialised. If there are lots of fields, create an object which encapsulates all their values. Create an enum for message types. Create a Map<MessageType, List<Object>>. Maybe one of those will permit you to initialise those fields faster.
 
Derik Davenport
Ranch Hand
Posts: 92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:No, you can't You can't override fields;
...
Don't go hiding fields; that way lies confusion and errors.

Thanks for contributing... I hope <fingers crossed> it was obvious in my posting that I already knew that I couldn't override a field and that I didn't want to have hidden fields either. I was trying to describe the problem and then describe the type of solution that I was hoping to find. The code I provided was a pedagogical example for that purpose, not exemplary code.

You initialise fields with the constructor and you initialise superclass fields with the super(...);

I did discuss that solution and the problems associated with it.

If there are lots of fields, create an object which encapsulates all their values.

As I said, that is a good solution for problem #1 of 2. If I defined the enum (good suggestion) or the Map in the parent class (or interface) then I could avoid a parallel hierarchy and keep the constants tied to the main parser hierarchy classes.

And so should whoever told you to call them child classes

LOL! I am guilty of anthropomorphising my classes. I have sibling classes (both derive directly from the same base class) and cousin classes too. YOu will know I have lost it when I start attributing gender.
 
Campbell Ritchie
Marshal
Posts: 66949
255
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Attribute genders and you go straight to MD
 
Bartender
Posts: 1845
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My suggestion:

remove the generator attribute from your abstract class, and add an abstract getter for it instead:


Your abstract class accesses the generator via this method (so you can still use it)
That accomplishes two of your goals: declaring that you can get the field, but not initializing it.

The compiler will enforce that you implement the method it a child class. It can't enforce that you do so intelligently though., so it isn't exactly the same thing as forced to initialize it in the constructor. I can't see any way to make this a compile time check though.


Just my two cents.
cheers,
Stefan
 
Campbell Ritchie
Marshal
Posts: 66949
255
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Will this work?
 
Sheriff
Posts: 21836
105
Eclipse IDE Spring VI Editor Chrome Java Ubuntu Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I hope getGenerator() is either private or final, because you shouldn't call overridable methods from constructors.
 
Campbell Ritchie
Marshal
Posts: 66949
255
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Obviously it won't work then.
 
Derik Davenport
Ranch Hand
Posts: 92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:Will this work?


Campbell,
The very first time I ran into this pattern (the need to override fields in a sub-class) that is exactly how I solved it. It blew up in my face about a year later.
Ever since then I have been using dependency Injection like I demonstrated in my original post. But I have had a few instances recently where the pattern fails for one or both of the 2 reasons I cited. It has happened 3 times in the last 2 weeks that I had one of those 2 problems.
 
Campbell Ritchie
Marshal
Posts: 66949
255
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
As I said when Rob mentioned the bit about final/private, it obviously won't work. Sorry. No more ideas myself, I am afraid.
 
Ranch Hand
Posts: 50
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think it's very likely that you should take your difficulties as a design smell - i.e. rethink your wider design, rather than trying to hack the existing one to make it work.
It violates the Liskov substitution principle for a start - and that's a very sensible principle 99% of the time. When I find myself in difficulty, and then notice that I'm violating some generally sound principle, then it's normally a sign to me that I've gone down the wrong path somewhere.

In your example it also looks as though your classes are far too aware implementation details. Does the parser implementation really have to construct the generator?

And then when your code is less tangled, would you really need that compile-time protection? That's what unit tests are for (when your code is built using the correct abstractions).
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Be very careful with your constructors and initializers too (one of the posts was talking about trying whacky things here). The JVM will execute the super constructor first, including methods invoked, and then it will initialise any fields in the subclass (potentially undoing what was done in the superclass constructor) before it then proceeds with the rest of the subclass constructor.
 
Derik Davenport
Ranch Hand
Posts: 92
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Aaron Shawlington wrote:I think it's very likely that you should take your difficulties as a design smell - i.e. rethink your wider design, rather than trying to hack the existing one to make it work.

I agree. It is possible that some creative refactoring would solve my problem.. You asked 'Does the parser need to construct the Generator'. No, but in this example I have stipulated that it must use one. But perhaps there is a way to refactor so that I don't need to use one, or that the methods that rely on Generator could be grouped in Generator on within a class that contains a generator. I would have to think about it in terms of a real world example.

It violates the Liskov substitution principle for a start - and that's a very sensible principle 99% of the time.

I am not sure I understand the application of Liskov very well. I once believed that it just meant that I shouldn't be allowed to create a subclass that made the method of a parent class have a more restrictive scope or throw an exception not thrown by the parent class. And that doesn't really apply. I did a quick google on Liskov and found that some people interpret it much more liberally. For some people, overriding any method would be a violation. Whatever the correct interpretation of Liskov is, my problem would still exist if the child class had not overriden any methods of the parent (abstract) class.

In my original code I made the parent class abstract so that this would not be an issue. Moreover, I created an Interface for the Parent class. When I created that interface, it was my intention to state that usage of any instance of any concrete class (a subclass of AbstractMessageParser) would be accessed only through the interface. I am genuinely unsure of how to apply Liskov to that condition. Clearly, if I made HtmlParser derive from SmtpParser, then yes, that would certainly fail some kind of smell test. Is that Liskov?

 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Derik Davenport wrote:

Aaron Shawlington wrote:I think it's very likely that you should take your difficulties as a design smell - i.e. rethink your wider design, rather than trying to hack the existing one to make it work.

I agree. It is possible that some creative refactoring would solve my problem.. You asked 'Does the parser need to construct the Generator'. No, but in this example I have stipulated that it must use one. But perhaps there is a way to refactor so that I don't need to use one, or that the methods that rely on Generator could be grouped in Generator on within a class that contains a generator. I would have to think about it in terms of a real world example.

It violates the Liskov substitution principle for a start - and that's a very sensible principle 99% of the time.

I am not sure I understand the application of Liskov very well. I once believed that it just meant that I shouldn't be allowed to create a subclass that made the method of a parent class have a more restrictive scope or throw an exception not thrown by the parent class. And that doesn't really apply. I did a quick google on Liskov and found that some people interpret it much more liberally. For some people, overriding any method would be a violation. Whatever the correct interpretation of Liskov is, my problem would still exist if the child class had not overriden any methods of the parent (abstract) class.

In my original code I made the parent class abstract so that this would not be an issue. Moreover, I created an Interface for the Parent class. When I created that interface, it was my intention to state that usage of any instance of any concrete class (a subclass of AbstractMessageParser) would be accessed only through the interface. I am genuinely unsure of how to apply Liskov to that condition. Clearly, if I made HtmlParser derive from SmtpParser, then yes, that would certainly fail some kind of smell test. Is that Liskov?



As an aside, my understanding has always been that in simple terms the principle means that you should be able to swap a superclass instance for a subclass instance without breaking the semantics of your program.

I was thinking about this last night on the way home from work. I decided that perhaps it isn't really a Liskov violation - but it just has (to me) a Liskov kind of smell to it (not very helpful I'm sure). I think it's just because your abstract class feels too 'involved' with the responsibilities of it's subclass instances - a side effect of wanting this compile time validation I suppose.



 
Marshal
Posts: 24813
60
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've seen other threads where people try to write a class which can control how its subclasses override it. I think this is the code smell you're referring to, Aaron. Anyway they always seem to generate a lot of discussion but no practical results. My feeling is that if somebody overrides a class in such a way that a NullPointerException is thrown, then that's their problem and they should fix it. Trying to write code which prevents subclass writers from making mistakes is, um, a mistake itself.

As for this part of the question:

Derik Davenport wrote:Because sometimes the fields refer to heavy weight objects, I do not want the fields instantiated by the parent's constructor and then immediately replaced by the child's constructor.



I would have the fields instantiated by lazy initialization. Presumably the fields are already private with an overridable getter method to expose them to the world, so that getter could be written to initialize the field upon its first call. (I haven't read the whole thread so if this was already proposed, sorry for the duplication.)
 
The moth suit and wings road is much more exciting than taxes. Or this tiny ad:
Sauce Labs - World's Largest Continuous Testing Cloud for Websites and Mobile Apps
https://coderanch.com/t/722574/Sauce-Labs-World-Largest-Continuous
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!