Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Any way to call a method in a higher class?

Status
Not open for further replies.

TheObserver

Programmer
Mar 26, 2002
91
0
0
US
Is there any way to call a method in an ancestor class?

For instance:

public class A
{
public A()
{
B myB = new B();
}

public methodA()
{
System.out.println("Hola");
}
}

public class B
{
public B()
{
methodB();
}

public methodB()
{
A.methodA();
}
}

I know about "extends" but I'm not sure it will work as I intend it to. Also, in the case of my actual code, the class (at the same level as class B above) already extends JFrame, and I don't know of a way to do multiple "extends".

Thanks for your time.
 
create a class (A) what extends your JFrame and after that create another class B what extends A.
Also you may create an interface A and create B with extending JFrame and implementing A (see keyword implements). With implementing you may inherit as many interfaces as you wish.

Ion Filipski
1c.bmp
 
If B extends A, B may call a A method with super:

super.methodA ();

If A already extends JFrame, B extends JFrame as well.
Remember the 'is a' analogy.
If A is a JFrame, and B is an A, B is a JFrame too.

seeking a job as java-programmer in Berlin:
 
There are serveral ways to do that. But first, you have to notice that in your code Class A and Class B are not related at all.

In this case, I mean, if your classes are not related, you may want to use composition instead of inheritance. That's to say, you can create a wrapper (or Adpater).

Sample code
Code:
class Adaptee{
    public void adaptedOperation(String text){
        System.out.println(text);
    }
}

class Adapter{
    private Adaptee adaptee;

    public Adapter(){
        adaptee = new Adaptee();
    }

    public void doOperation(){
        adaptee.adaptedOperation("Called from adapter");
    }
}

public class Application {

    public static void main(String[] args) {
        Adapter adapter = new Adapter();
        adapter.doOperation();
    }
}

But this approach may have disadventages if you have to make a class hierachy out of Adapter.

Another perpective is inheritance (which seems to be the one that you sugest)

There are two ways to do it.

Sample code
Code:
class A extends JFrame{
    public void myOperation(){
        System.out.println();
    }
}

class B extends A{
    public void anotherOperation(){
        //Calls class A method
        this.myOperation();
        //Calls JFrame method
        this.getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
    }
}

But to do this you have to inherit twice. That´s to say, A must first inherits from JFrame, so that you can add a new method and then you make B inherit from A to call that method, besides the methods of JFrame. All this because Java does not have multiple inheritance and you cannot make class B inherits from JFrame and class A at the same time.

So, there is another way to do it. You can build an interface which is a protocol that tells the implementor classes which methods they shall implement.

Code:
//Interface just declares methods, but do not implement them
interface A{
    public void doSomething();
}

//Inherits from JFrame and implements the interface methods
class B extends JFrame implements A{
    public void doSomething() {
        System.out.println("I implemented doSomething");
        getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));
    }

}

Now, evidentrly, when you use inheritance any subclass can call the methods of its parent class, as you can see in the samples above, I call the getContentPane() methods of the JFrame class.

I hope it helps.

edalorzo@hotmail.com
 
Maybe a horrible metaphor will help clear up what I'm doing.

Class A would be like a word processor app. Class B would be a document object. I need class B to notify class A when it has changed so that class A can serialize the document to the filesystem.

I also need to support deserialization notification from class B to class A. But if we solve one, we solve both, or at least I'd think so.

I've tried having the serialization at the level of class B, but there was a ton of overhead involved in having class B "unload" a current instance of itself and then "load" a serialized instance. This is why the saving/loading was moved up to the class A level.

Class A is nothing more than a shell class to instanciate and manage instances of class B. Class A has no GUI components. Unless I can inherit JFrame in class B by extending it in class A, and have everything work correctly in class B (read: work as it did before), there would be no advantage to doing that.

I've thought of trying to split the GUI components up between A and B related to their functionality, but most would still reside in B and then I'd have the problem of "using up" my extends in both classes and not really solving the problem.

I've also thought of using a flag variable in B and having A check it periodically (with a timer class or similar), but that would seem to be inefficient and possibly intensive enough to slow down other functionality not related to these two classes.

Thanks for your replies.
 
Have you tried getParent()?

public class A
{
public A()
{
B myB = new B();
}

public methodA()
{
System.out.println("Hola");
}
}

public class B
{
public B()
{
methodB();
}

public methodB()
{
((A)getParent()).methodA();
}
}

Phil
 
I tried extending A with JFrame and then extending B with A. However, when I instantiated A, it would get stuck in some sort of loop when it hit the instantiation of B - it never REALLY instantiated B, it just kept looping through the method in A where I was attempting to instatiate B.

I have it working right now via two boolean "flags" in B and a Timer/TimerTask in A. The Timer/TimerTask is started when A is instantiated (in the constructor) and checks the state of the two booleans in B after it has been instantiated, determining a course of action based on which flag is set to true. It seems to work, but I need to test further to see if it actually is working correctly.

I hadn't thought about getParent. I completely forgot about that. I'll give it a try.

Thanks for your reply.
 
Maybe you should try a Java Beans Approach. When data changes in class B you have to notify to one or more objects who registered their listeners with class B object.

Please give it a look at this sample code I took from Robert Englader Book: Developing Java Beans

You can copy it and run it. I tested myself in InteliJ and it's ok. In this case when temperature changes in the Thermometer object it fires events in the application object who registered its listener with Thermometer.

Code:
import java.util.Vector;

//Use this object to comunicate the change of data (The Model) between classes
class TemperatureChangeEvent extends java.util.EventObject{

    //This is the information you want to interchange in the event
    protected double theTemperature;

    public TemperatureChangeEvent(Object source,double temperature) {
        super(source);
        this.theTemperature = temperature;
    }

    public double getTemperature(){
        return this.theTemperature;
    }
}

//Now declares a listener interface of your kind of event
interface TemperatureChangeListener extends java.util.EventListener{
    //This method is call whenever temperature changes
    void temperatureChanged(TemperatureChangeEvent event);
}

//Now the event source
class Temperature{
    protected double currentTemperature = 22.2;
    private Vector listeners = new Vector();

    public Temperature(double startingTemperature){
        this.currentTemperature = startingTemperature;
    }

    //This method will fire the events
    public void raiseTemperature(){
        this.currentTemperature++;
        this.notifyTemperatureChange();
    }

    //Register event handlers for temperature
    public void addTemperatureChangeListener(TemperatureChangeListener l){
        if (!this.listeners.contains(l)){
            this.listeners.add(l);
        }
    }

    //Remove listeners from the class
    public synchronized void
    removeTemperatureChangeListener(TemperatureChangeListener l){
        if (this.listeners.contains(l)){
            this.listeners.remove(l);
        }
    }

    //Notify all listening objects of the temperature change
    protected void notifyTemperatureChange(){
        //Creates the event object
        TemperatureChangeEvent event = new TemperatureChangeEvent(this,currentTemperature);

        //Make a copy of the listener object list so that it cannot be change while
        //firing events
        Vector tmpVector;
        synchronized(this){
            tmpVector = (Vector) this.listeners.clone();
        }
        //fire events
        int cnt = tmpVector.size();
        for (int i=0;i< cnt; i++){
            TemperatureChangeListener client = (TemperatureChangeListener) tmpVector.elementAt(i);
            client.temperatureChanged(event);
        }
    }
}


//This application is listener for temperature chage
public class Application implements TemperatureChangeListener{
    public static void main(String[] args) {
        
        Application app = new Application();
        Temperature thermometer = new Temperature(22.2);
        
        //Register the listener in the thermometer object
        thermometer.addTemperatureChangeListener(app);
        
        thermometer.raiseTemperature();
    }

    //This is what happens when temperature change
    public void temperatureChanged(TemperatureChangeEvent event) {
        System.out.println("Temperature just change to "+event.theTemperature);
    }
}

I hope it helps.

edalorzo@hotmail.com
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top