Click to See Complete Forum and Search --> : Java question - inheritence and constructors


klamath
10-07-2000, 04:07 PM
Here's an example of the problem I'm having:


import javax.swing.*;

public class Test extends JButton {
Test() {
if (java.lang.Math.random() > 0.5) {
super("Foo");
} else {
super("Bar");
}
}
}

I get the following errors from javac:


Test.java:8: call to super must be first statement in constructor
super("Foo");
^
Test.java:10: call to super must be first statement in constructor
super("Bar");


This is a stupid example of a problem I'm having. I want to initialize an object with the results of a PRNG. Can someone help out this Java newbie?

------------------
- Klamath
Get my GnuPG Key Here (http://klamath.dyndns.org/mykey.asc)

Larkfellow
10-07-2000, 04:42 PM
Originally posted by klamath:
Here's an example of the problem I'm having:
...

Test.java:8: call to super must be first statement in constructor
...


If you want to make a call to super, you have to use super("foo"); as you very first statement in the Test() constructor. You can't have an if statement before it. The best way to do what you want is to have it so that you call test like this:

if(...){
Test("foo");
}else{
Test("bar");
}

And inside the test constructor you'd just have this:

Test(String x){
super(x)
...
}

klamath
10-07-2000, 05:07 PM
I know, but that's kinda annoying. That means everywhere I create a 'Test' object, I need to put all that conditional code.

Is there anyway to do this the way I was trying to?

I'm actually using this(), not super() (although the compiler warning and your recommendation) is the same. I want to initialize an object with a couple params, but I also want to give the developer the option of not specifying these params (in which case, they should be randomly generated).

------------------
- Klamath
Get my GnuPG Key Here (http://klamath.dyndns.org/mykey.asc)

Larkfellow
10-07-2000, 06:38 PM
Originally posted by klamath:
...
I want to initialize an object with a couple params, but I also want to give the developer the option of not specifying these params (in which case, they should be randomly generated).


Okay, I'm starting to see you're problem then... And I think that the only way (I can think of now at least) around it is not to use this(), insted you'll more or less have to have 2 completely written out constructors. I'll let you know if anything else comes to mind..

Dru Lee Parsec
10-08-2000, 10:06 PM
The super() can only be called as the first line of a constructor. Since what you really want to do is to change the text of JButton then simply use
setText("foo");

A JButton itself doesn't have a setText() method, but it does inherit one from AbstractButton.

klamath
10-08-2000, 11:17 PM
Yeah, that will suffice for this case. But in general (when the params to the constructor can't be changed later), I guess I'm SOL.

Anybody else have any ideas?

Thanks to everyone who's helped me so far.

------------------
- Klamath
Get my GnuPG Key Here (http://klamath.dyndns.org/mykey.asc)

Dru Lee Parsec
10-09-2000, 12:54 PM
ut in general (when the params to the constructor can't be changed later), I guess I'm SOL.

Actually no. The classes in Java are designed such that there shouldn't be anything that you can do in a contructor that you can't do via methods later.

The super(); statement is usually called only to set up the most basic attributes. For example: take a look at JDialog. It has constructors that take a JFrame as a parent or another JDialog as a parent. If your main frame (usually a JFrame) has a icon set for the upper left corner then one of the things a JDialog can do is to is pick up that icon automatically from it's parent.

So, let's day your wrote your own dialog box the extends JDialog called PositionDialog. And your PositionDialog is simply a JDialog that will automatically position itself in the middle of the screen. Since you want your dialog box to pick up the proper icon from the frame you would probably have a constructore that looked something like this:



public class PositionDialog extends JDialog{

public PositionDialog(JFrame parent){
super(parent);
// set the title and stuff later
}

// methods go here
}


Since the JDialog constructor already has the code to link the dialog to it's parent and set up the icon you use super(parent) to use the JDialog code to do that. Of course, JDialog must have a constructor that takes a JFrame for this to work.

There's a reason that the super line must be the first line in the constructor. For an object to exist, it must have been constructed (or at least be IN the constructor which means the memory has been allocated). Since an object exist, it's parent object must have also been constructed. The super() line says "Construct my parent using whatever parameter list I pass it via my super statement".

The current object is not constructed until the parent object is constructed. So if you try to put an if statement in the constructor and then try to call "super()" then you're saying 2 things:

1. My object is constructed enough for me to run the if statement code, and
2. My object is not constructed because the super() hasn't constructed my object's parent yet.

Did that make sense? I hope so. Basically, your faking out the compiler by tryig to execute code in an object that hasn't been constructed yet.

Keep hacking.

DLP

klamath
10-09-2000, 01:44 PM
The classes in Java are designed such that there shouldn't be anything that you can do in a contructor that you can't do via methods later.

Except that the parameter I'm trying to change is used as the value of a 'final' field. So that once the field is assigned a value (via the no-arg constructor), it can't be changed. Here's a real world example: let's say the object I'm initializing is a big group of daemon threads, each of which takes lots of RAM and CPU time. The constructor is passed the number of threads to start, and by default starts a lot (lets say 15 or 30). If I really want to start a random number of threads from 1 to 3, it's kinda annoying to spawn 30 threads and then kill 27 of them.

I realize though, that I'm trying to do something you're not really supposed to do. Thanks for the info everyone.

------------------
- Klamath
Get my GnuPG Key Here (http://klamath.dyndns.org/mykey.asc)

fafnir
10-10-2000, 01:37 AM
I know it's ugly but would this solve you problem?

Test() {
super(java.lang.Math.random() > 0.5 ? "Foo" : "Bar");
}

(I am pretty sure this works but I haven't compiled it.)

Sterling
10-10-2000, 08:10 AM
fafnir - Just what I was going to suggest. That should work, because there aren't actually any statements before the super() call.

------------------
-Sterling
-This post made with the Lizard! (http://www.mozilla.org)

klamath
10-10-2000, 12:28 PM
Thanks everyone. That should work.

------------------
- Klamath
Get my GnuPG Key Here (http://klamath.dyndns.org/mykey.asc)

jask
10-10-2000, 03:01 PM
Originally posted by fafnir:
I know it's ugly but would this solve you problem?

Test() {
super(java.lang.Math.random() > 0.5 ? "Foo" : "Bar");
}

(I am pretty sure this works but I haven't compiled it.)

Could you explain how that works - the (test ? "..." : "...")

Thanks