• 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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Parent Functions and Child Functions

 
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all!

My problem is best described with the following code:



My issue is that this is the output I would have expected:

--- Parent: ---
p foo
p bar
--- Child: ---
c foo
p foo
p bar

But this is what's actually happening:

--- Parent: ---
p foo
p bar
--- Child: ---
c foo
p foo
c bar
p bar

Obviously, this must be the intended functionality of Java, but am I the only one surprised by that? The parent function will actually call the child's function before its own? What do I do if I want (which I do) the parent foo just to call its own version of bar? (this.bar() does not make any difference).

(For those wondering, here's what I want to do in more detail. I have an ImagePanel object and a GameObject which extends ImagePanel. ImagePanel contains all sorts of scaling, rotation, and text functionality, and I want to keep it as modular as possible so that I can use it for pretty much any image, in this project and others. GameObject adds things like collision detection - and simplifies my filenames by knowing to throw "/images/" and ".gif" around any filename it gets. So I want to have its constructor call the ImagePanel constructor with the modified filename. I also want to have a setImage function which allows me to change the image later. GameObject calls the super setImage, but only after modifying the filename. The problem is that ImagePanel's constructor actually calls setImage, and when that happens it modifies the filename twice, giving me "/images/images/something.gif.gif". I could, I suppose, simply remove the modification from GameObject's constructor, but that's assuming that ImagePanel's constructor is never rewritten.)

Thanks!!
 
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rendelle Fox wrote:
Obviously, this must be the intended functionality of Java, but am I the only one surprised by that? The parent function will actually call the child's function before its own? What do I do if I want (which I do) the parent foo just to call its own version of bar? (this.bar() does not make any difference).


I'm afraid I can't tell you if you're the only one surprised by that.

The parent function is not calling the child function: the main program is calling the function, and if the object on which it is calling the function is a child, then the child's function is the one that will get called. That's how Java (and C++ virtual functions) work; if you ever hear the term "polymorphism", this is what they mean by it.

You create an object of a particular class; each method on that class is an action you want the object to perform on the caller's behalf. If what you want is for the parent function to be called, then the child need not override the method, in other words, your ChildClass does not need to have a foo() at all, the caller will still be able to call c.foo() and the ParentClass.foo() code will be executed.

The only reason for the ChildClass to have a foo is if you want it to do anything different from or in addition to the ParentClass.foo().

Constructors are a little different; if you have a Constructor with a parameter in a superclass, and you want to be able to invoke a constructor on the subclass with the same parameter, you must declare such a constructor in the subclass. If all you want that class to do is call the superclass constructor, just have it invoke super(parameter); as its first (and perhaps only) statement.

And if a constructor of a class has a particular behavior, and is rewritten to change that behavior, then it is reasonable that any invocation of that constructor must also change. I don't think there's any way to write calls to constructors so that they are insulated against changes of contract with the constructor.

rc
 
Rendelle Fox
Greenhorn
Posts: 20
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I had thought I understood all about polymorphism and overriding methods. I mean, of course if I call c.bar() I expect to see c's bar which may or may not call the parent's bar as well, depending on how it is written. I just don't think I ever encountered the situation where you override a function that the parent class is calling somewhere, and that breaks the parent class. (Or maybe I just assumed something elsewhere was calling it - like if you override paintComponent and forget to call super, I knew that would break things).

The thing is, I want to have both ParentClass and ChildClass with a foo (this is actually my constructor in my real program) and a bar. I need ParentClass to be able to act on its own, so it needs both. But I also want ChildClass to override both. So are you saying that is it simply not possible to force a particular call to bar within the parent's foo to call its own bar, even if it has been overridden?
 
Marshal
Posts: 79178
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Don't say "parent" and "child", say "superclass" and "subclass". In GUIs, the terms "parent" and "child" are in common use for windows inside windows.

As Ralph Cook says, constructors and methods are quite different from each other. NB: If you invoke a method from a constructor, mark that method private or final. (I am not sure whether you can use private and final together). That will force the JVM to use the un-overridden method. If there is an overridden method invoked polymorphically, that might do something different from what you expect or want.

If you want a subclass method to use the superclass method as part of its activity, you can write super.foo();. Unlike super() for constructor calls, this can be anywhere in the method.
Called methods are polymorphic too; if you are in a class, you will get the overridden method.

[campbell@campbell1110 java]$ javac SuperClass.java
[campbell@campbell1110 java]$ java SuperClass
SuperClass foo super-bar
SubSub: sub-bar
SubClass foo sub-bar
[campbell@campbell1110 java]$

The super.foo(); call in the subclass calls the superclass method. But notice what happens. The getClass() invocation returns the SubClass object, and the bar() method returns sub-bar. you are getting the overridden methods from the subclass.
Clicking "polymorphism" where it is underlined (eg in your second post) might give more useful help. The Wikipedia article has "This article's factual accuracy is disputed" in; I think that article won't help you much at present.
 
Campbell Ritchie
Marshal
Posts: 79178
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Don't confuse methods and constructors. Constructors aren't overridden. Try only calling private methods from your constructors. Private methods aren't polymorphic; if you have private methods with the same signature in superclass and subclass, the compiler will see them as completely independent of each other, not overriding.
 
Ralph Cook
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rendelle Fox wrote:I had thought I understood all about polymorphism and overriding methods. I mean, of course if I call c.bar() I expect to see c's bar which may or may not call the parent's bar as well, depending on how it is written. I just don't think I ever encountered the situation where you override a function that the parent class is calling somewhere, and that breaks the parent class. (Or maybe I just assumed something elsewhere was calling it - like if you override paintComponent and forget to call super, I knew that would break things).

The thing is, I want to have both ParentClass and ChildClass with a foo (this is actually my constructor in my real program) and a bar. I need ParentClass to be able to act on its own, so it needs both. But I also want ChildClass to override both. So are you saying that is it simply not possible to force a particular call to bar within the parent's foo to call its own bar, even if it has been overridden?



One of the things I think interferes with descriptions of code is pronouns, especially personal pronouns, in reference to code execution.

"... where you override a function that the parent class is calling somewhere ..." -- I cannot tell what you are talking about here.

".. I also want ChildClass to override both ..." -- just for the sake of overriding the methods, or because ChildClass needs some kind of additional functionality?

There is also a point where generic names for things -- ParentClass, ChildClass, foo, bar -- interfere with software discussion, especially design discussion. It is difficult to tell if ChildClass should even extend ParentClass, because we don't know what either class is supposed to represent; since we don't know that or what the methods are supposed to do, we cannot tell whether overriding the methods is necessary, or a good or a bad idea, or what.

A more concrete example would help, and we could concoct one that had some kind of real-world presence so that it was easier to discuss whether doing something made good design sense.

I will throw out another thought in terms of class design, which includes decisions about subclassing and overriding -- there is a limited use in thinking of a class in terms of its superclass(es). Yes, if I use a Properties object, it is good to know that it is a special case of a Hashtable, so that I know how to get things into and out of the Properties object if I already know about Hashtables, but it doesn't usually extend to knowing whether a method call will call its superclass equivalent. Properties has a contract with its users; its constructors and methods are published to work the way they work, and I do not have to know any details about methods calling superclass methods to know what they do. That's the way it should be.

rc
 
Campbell Ritchie
Marshal
Posts: 79178
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Agree with Ralph Cook that there has been some loose nomenclature and vocabulary on this thread.
Don't say "parent" and "child".
Don't say "function"; it's called "method". Even if we did say "function", those methods aren't functions because a function returns a value and those methods are void return type.
There has been confusion about whether foo was a method or a constructor. Methods and constructors are different, so you should always be clear about whether you are describing methods or constructors. The only thing you can override and see polymorphism with (in Java™) is an instance method. Nothing else can be overridden in Java™.
I didn't think a concrete example was necessary, but I have written one anyway; note the unusual spelling of one of the classes because I already had a Cat class which I didn't want to change.

[campbell@campbell1110 java]$ java Menagerie
Newborn Catt: Miaow! Purrrrr! Meow
Newborn Dog: Woof! Woof!
Newborn Animal: Uggggh!
Animal kicked:
Catt kicked: Spit! Sssssssssssszzss
Dog kicked: Grrrrrrrrrrrrrrrr!
[campbell@campbell1110 java]$

. . . so you see, I am a cruel so-and-so who kicks dogs. Also that the constructor and instance methods both call other methods polymorphically. You can try changing the visibility of the makeNoise method to private and see what happens. I said yesterday you should mark any methods called from your constructor private (or final, which I forgot). Otherwise, you might not be breaking your class, but you are getting behaviour you hadn't expected. I would reserve "breaking the class" for instances where the class invariants are breached.
Try changing the declared types of the three objects to Animal in all instances, and see what difference that makes.
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic