-2

Possible Duplicate:
force base class to use its own method and not overrided method

Suppose I have these classes — sorry, it's kind of hard to think of a simple example here; I don't want any why-would-you-want-to-do-that answers! –:

class Squarer
{
    public void setValue(int v)
    {
        mV = v;
    }
    public int getValue()
    {
        return mV;
    }
    private int mV;
    public void square()
    {
        setValue(getValue() * getValue());
    }
}

class OnlyOddInputsSquarer extends Squarer
{
    @Override
    public void setValue(int v)
    {
        if (v % 2 == 0)
        {
            print("Sorry, this class only lets you square odd numbers!")
            return;
        }
        super.setValue(v);
    }
}

// auto s = new OnlyOddInputsSquarer();
OnlyOddInputsSquarer s = new OnlyOddInputsSquarer();
s.setValue(3);
s.square();

This won't work. When Squarer.square() calls setValue(), it will go to OnlyOddInputsSquarer.setValue() which will reject all its values (since all squares are even). Is there any way I can override setValue() so that all the functions in Squarer still use the method defined there?

PS: Sorry, Java doesn't have an auto keyword you haven't heard about! Wishful thinking on my part.

Edit: I can't modify Squarer!

Community
  • 1
  • 1
Timmmm
  • 88,195
  • 71
  • 364
  • 509
  • 2
    Instead of snarkily making up keywords, you could use actually valid Java code in your questions. Or go back to C++. – millimoose Nov 22 '12 at 10:59
  • 1
    duplicate of http://stackoverflow.com/q/7520359/925202 – PC. Nov 22 '12 at 10:59
  • 1
    Also, no, this isn't possible. The very **point** of overriding the method is so the inherited methods will invoke your override. Otherwise it'd be shadowing. – millimoose Nov 22 '12 at 11:00
  • If you don't want that method to be overriden, declare it as final. – Pablo Nov 22 '12 at 11:02
  • @Pablo That way you will never be able to use the overriden method in a loop without using `instanceof` to find out if it is a child class or not, which is not an advisable thing to do, depending on what you want to do. With the code example here I can't really figure out if iterating is wanted or not. – Strike Nov 22 '12 at 11:08
  • @Pablo: I don't control the base class code. – Timmmm Nov 22 '12 at 11:12

2 Answers2

0

It seems to me that the class Squarer is not well designed. If you really need a dirty trick to make this work, you could also override the method square():

class OnlyOddInputsSquarer extends Squarer
{
    @Override
    public void setValue(int v)
    {
        if (v % 2 == 0)
        {
            print("Sorry, this class only lets you square odd numbers!")
            return;
        }
        super.setValue(v);
    }
    @Override
    public void square()
    {
        super.setValue(getValue() * getValue());
    }
}

But... a square of a odd number is not even, so this should not really be a problem. I suppose this is just an example and your real problem is different.

Edit: OK, if this doesn't work, there is even a dirtier method: in setValue check the stack and if it was called from square call super.setValue instead. I don't recommend this, but If you really really need to get this done, check here to see how to do it.

Community
  • 1
  • 1
Pablo
  • 3,655
  • 2
  • 30
  • 44
  • Err yeah, good point about squaring odd numbers! I should have called it `Doubler` or something. Anyway sadly I can't do that, since in my real problem, `square()` uses some private methods. Thanks anyway though. – Timmmm Nov 22 '12 at 11:28
  • @Timmmm OK, there is another "option". I edited my answer. – Pablo Nov 22 '12 at 11:38
0

This would be relatively painless solution I think. It postpones the check until the actual squaring is done.

public class OnlyOddInputsSquarer extends Squarer {

    @Override
    public void square() {
        if (getValue() % 2 == 0) {
            throw new IllegalStateException("Sorry, this class only lets you square odd numbers!")
        }
        super.square();
    }

}

And here is its unit test (requires JUnit):

public class OnlyOddInputsSquarerTest {

    @Test
    // normally this case would be in a separate test
    public void testSuperclass() {
        Squarer squarer = new Squarer();
        squarer.setValue(3);
        squarer.square();
        Assert.asserEquals(9, squarer.getValue());
    }

    @Test
    public void testOddValue() {
        OnlyOddInputsSquarer oddSquarer = new OnlyOddInputsSquarer();
        oddSquarer.setValue(3);
        try {
            oddSquarer.square();
            Assert.fail("Expected IllegalStateException");
        catch(IllegalStateException e) {
            // expected
        }
    }

    @Test
    public void testEvenValue() {
        OnlyOddInputsSquarer oddSquarer = new OnlyOddInputsSquarer();
        oddSquarer.setValue(4);
        oddSquarer.square();
        Assert.asserEquals(16, squarer.getValue());
    }

}
Adriaan Koster
  • 15,870
  • 5
  • 45
  • 60