views:

133

answers:

7

Firstly I'm extending an existing class structure and cannot alter the original, with that caveat:

I would like to do this:

class a
{
   int val;

   ... // usual constructor, etc...

   public int displayAlteredValue(int inp)
   {
     return (val*inp);
   }
}

class b extends a
{
   ... // usual constructor, etc...

   public in displayAlteredValue(int inp1, int inp2)
   {
     return (val*inp1*inp2);
   }
}

As I said before I cannot alter class a and I want to maintain the function name displayAlteredValue rather than making a new function. If this can be done I only have to change a few instantiations of a to instantiations of b. I don't want to spend a lot of time replacing the many function calls to displayAlteredValue. (And yes I do realise there are such things as search and replace however for other reasons, doing that would be problematic).

Any ideas?

A: 

what if you add this to your derived class

public int displayAlteredValue(int inp)
{
  return super.displayAlteredValue(inp);
}
Lou Franco
Why bother? By deriving the class, any calls to displayAlteredValue already do this.
erickson
No they don't. Look up the difference between method overloading and method hiding.
DJClayworth
I'm talking about calls with this signature, not calls to the overloaded method. This answer is recommending an override of A's definition, not an overload, which simply invokes A's definition, and is pointless.
erickson
+2  A: 

You can overload a function in a derived class. So what you have specified above should work. Just wrote a quick test and it worked.

public class DerivedOverload {

    /**
     * @param args
     */
    public static void main(String[] args) {
     A classA = new A(); 

     B classB = new B();

     System.out.println("DerivedOverload.main() classA.displayAlteredValue(2) : " + classA.displayAlteredValue(2));

     System.out.println("DerivedOverload.main() classA.displayAlteredValue(2) : " + classB.displayAlteredValue(2,2));
    }



}


class A
{
   int val = 2;

   A(){

   }

   public int displayAlteredValue(int inp)
   {
     return (val*inp);
   }
}

class B extends A
{
   B(){

   }

   public int displayAlteredValue(int inp1, int inp2)
   {
     return (val*inp1*inp2);
   }
}

System out. DerivedOverload.main() classA.displayAlteredValue(2) : 4 DerivedOverload.main() classA.displayAlteredValue(2) : 8

Feet
A: 

The code you've written compiles as-is. You've basically just overloaded the method. What does the code you posted not accomplish, that you want to accomplish? Are you trying to stop people from calling b.displayAlteredValue with a single argument? If so, you can't do that (at compile time) as it would violate Liskov's Substitutability Principle.

You could throw an exception, but that wouldn't be terribly nice.

Alternatively, you could use composition instead of inheritance - but really we'd need to know more about the situation to know whether that was suitable.

Jon Skeet
A: 

What you have looks fine to me.

Instances of class b will have access to both versions of the method. Calls to the 1-argument version will be automatically routed to class a. Calls to the 2-arg version will go to class b.

Instances of class a will only have access to the 1-arg version though, but I don't think there's a way around that.

Clayton
+1  A: 

I'm not clear what the issue is. You absolutely can create a subclass b which has a method of the same name but different signature.

One possible issue you might be running into is that the compiler needs to know that the type of the object is b, not a, in order to call the method that only exists in b.

So code like this won't work:

// this works because b is a subclass of a
a anObject = new b();

// this will not compile because the declared type of an Object is a
int x = anObject.getValue( 1, 2 );

You would have to either change the declaration of the variable to type b, or cast it to b whenever you want to call the 2-argument method.

Dave Costa
A: 

You could write the code in class B as follows:

public int displayAlteredValue(int inp) 
{
    return -1;
}

and indicate on the function that -1 is an error return. For int this doesn't really work, but if you returned a class, you could return null if they call the single parameter version of the method.

Elie
A: 

Alternatively, you could consider favoring composition over inheritance since the class you are extending comes from a different package.

http://www.artima.com/lejava/articles/designprinciples4.html

Clay