Partially overriding a method?

R

raphfrk

I was wondering if it is possible to override a method but only for
certain sub-classes of the method that the super-class supports.

For example:

class MainClass {

public static void main(String[] args) {

System.out.println("Started");

MainClass mc = new SubClass();

mc.check("Testing");
mc.check(7);

}

void check(Object x) {
System.out.println(x.toString());
}

}


class SubClass extends MainClass {

void check(String x) {
System.out.println("Sub class: " + x);
}

}

The call to mc.check() calls the main class's version of the method.

However, if I change the sub-class to:

class SubClass extends MainClass {

void check(Object x) {
System.out.println("Sub class: " + x);
}

}

then it uses the sub-class always.

One option would be something like:

class SubClass extends MainClass {

void check(Object x) {
if(x instanceof String) {
check((String)x);
} else {
super.check(x);
}
}

void check(String x) {
System.out.println("Sub class: " + x);
}

}

This would override and only use the sub-class for processing Strings.
 
L

Lew

I was wondering if it is possible to override a method but only for
certain sub-classes of the method that the super-class supports.

You need to clean up your language. In Java there is no such thing as a
"subclass of a method". Only classes have subclasses, or more generally, only
types have subtypes. Imprecise descriptions lead to error.

There is no such thing as "partially overriding a method" in Java. Use the
'@Override' annotation in your code. It will help you see that a method
either does or does not override another. It's binary, either-or,
black-and-white, is-or-is-not. Predictably, verifiably, completely, utterly
and as supported by '@Override', you can tell if a method is or is not an
override. Period.

For example:

class MainClass {

public static void main(String[] args) {

System.out.println("Started");

MainClass mc = new SubClass();

mc.check("Testing");
mc.check(7);

}

void check(Object x) {
System.out.println(x.toString());
}

}


class SubClass extends MainClass {

void check(String x) {
System.out.println("Sub class: " + x);
}

}

The call to mc.check() calls the main class's version of the method.

You should use the '@Override' annotation. Attempting to use it on
'SubClass#check(String x)' would have shown you that it does not override
'MainClass#check(Object x)'.
However, if I change the sub-class to:

class SubClass extends MainClass {

void check(Object x) {
System.out.println("Sub class: " + x);
}

}

then it uses the sub-class always.

Well, yeah. That's by design, yes?

Again, you should use '@Override' here. The reason the invocation in your
example calls the override is because that's the whole point of overrides!
One option would be something like:

class SubClass extends MainClass {

void check(Object x) {
if(x instanceof String) {
check((String)x);
} else {
super.check(x);
}
}

void check(String x) {
System.out.println("Sub class: " + x);
}

}

This would override and only use the sub-class for processing Strings.

Rather imprecisely phrased. If by that you mean, "'check(Object)' overrides,
but the specialization 'check(String)' does not, therefore references to the
latter through a 'SubClass' reference will not invoke the override," then you
are correct.

I took the liberty of turning your example into an actual SSCCE, something you
should have done. I've also changed the class names so that the stupid
compound part 'Class' is no longer part of them.

<sscce source="/com/lewscanon/eegee/DoesItOverride.java" >
package com.lewscanon.eegee;

/**
* DoesItOverride.
*/
public class DoesItOverride
{
/**
* main.
* @param args String [] argument array.
*/
public static void main( String [] args )
{
DoesItOverride doesIt = new Rider();
Rider orider = new Rider();

System.out.print( "doesIt: ");
doesIt.check( "Test doesIt" );

System.out.print( "doesIt: ");
doesIt.check( Integer.valueOf( 7 ) ); // eschew autoboxing

System.out.print( "orider: ");
orider.check( "Test rider" );

System.out.print( "orider: ");
orider.check( Integer.valueOf( 7 ) );
}

/**
* check.
* @param x Object.
*/
public void check( Object x )
{
System.out.println( "parent check(Object): "+ x );
}
}

class Rider extends DoesItOverride
{
@Override
public void check( Object x )
{
System.out.println( "subtype check(Object): "+ x );
}

/**
* check.
* @param x String - not an override.
*/
// @Override
/* ^^ Causes compilation error:
The method check(String) of type Rider
must override or implement a supertype method
*/
public void check( String x )
{
System.out.println( "subtype check(String): "+ x );
}
}
</sscce>

Output:

doesIt: subtype check(Object): Test doesIt
doesIt: subtype check(Object): 7
orider: subtype check(String): Test rider
orider: subtype check(Object): 7
 
M

markspace

I was wondering if it is possible to override a method but only for
certain sub-classes of the method that the super-class supports.


Yes and no. As you discovered, overriding is all or nothing. You
either override or you don't.

But you could add your own processing to do what you want with the
"super" keyword.

For example:

class MainClass {
public static void main(String[] args) {
System.out.println("Started");
MainClass mc = new SubClass();
mc.check("Testing");
mc.check(7);
}
void check(Object x) {
System.out.println(x.toString());
}
}

class SubClass extends MainClass {
void check(Object x) {
if( x instanceof String ) {
System.out.println("Sub class: " + x);
} else {
super.check( x );
}

The code changes above are untested.
 
L

Lew

Yes and no. As you discovered, overriding is all or nothing. You either
override or you don't.

But you could add your own processing to do what you want with the "super"
keyword.

For example:

class MainClass {
public static void main(String[] args) {
System.out.println("Started");
MainClass mc = new SubClass();
mc.check("Testing");
mc.check(7);
}
void check(Object x) {
System.out.println(x.toString());
}
}

class SubClass extends MainClass {
void check(Object x) {
if( x instanceof String ) {
System.out.println("Sub class: " + x);
} else {
super.check( x );
}

The code changes above are untested.

The presence of the 'instanceof' operation is often a red-flag marker of bad
design.

Polymorphism handles type resolution automatically. Doing it manually like
this is a big oops. Josh Bloch and other writers warn against overload
resolution on subtypes - it can be dicey.

If you have a concept that a particular method overload should be an override,
but the parent class doesn't sport that overload, you're trying to assert two
contradictory things. You're trying to say that 'check(String)' is an
override but that it isn't. As a result, you have to do funky type checks in
the subtype.

The upside is that you get what the OP asks for, if not what he wants - an
override that can specialize for a covariant argument type. The idiom in the
SSCCE I posted, as the output shows, will not treat 'check(String)' as a
specialization if the variable is of the supertype - the compiler will invoke
the 'check(Object)' form no matter what. It only knows about the
specialization through a reference of the subtype.

I'm not saying that the 'instanceof' dodge is a bad way to bandage an
infelicitous design, only that its necessity stems from such a decision.
Either 'check(String)' is part of the supertype contract or it isn't; trying
to pretend that it is via subtype magic is not a great thing. You could just
add the specialization to the parent type, or abandon the idea that you should
have a specialization at all. Or perhaps abandon the idea that you should
have a generalization in the supertype. OR ... you could make the
specialization a generics parameter:

public class DoesItOverride <T>
{
public void check( T x )
{
System.out.println( "Supertype: "+ x );
}
}
class Rider extends DoesItOverride <String>
{
@Override
public void check( String x )
{
System.out.println( "Subbatype: "+ x );
}
}
 
R

Roedy Green

I was wondering if it is possible to override a method but only for
certain sub-classes of the method that the super-class supports.

To get that sort of effect, create new methods with new names.

You can "rescue" a method being overridden, to give access to the
parent method, by creating a method with a new name or signature in
the same class you overrode the base method that calls the parent
method with super.xxxx.

--
Roedy Green Canadian Mind Products
http://mindprod.com
Politicians complain that Kindles and iBooks are killing jobs by
destroying the paper book industry. I see it that they have create a way
to produce books for less than a third the cost without destroying forests
and emitting greenhouse gases in the process. They have created wealth.
They are encouraging literacy and cutting the costs of education.
 
E

Eric Sosman

I was wondering if it is possible to override a method but only for
certain sub-classes of the method that the super-class supports.

For example:

class MainClass {

public static void main(String[] args) {

System.out.println("Started");

MainClass mc = new SubClass();

mc.check("Testing");
mc.check(7);

}

void check(Object x) {
System.out.println(x.toString());
}

}


class SubClass extends MainClass {

void check(String x) {
System.out.println("Sub class: " + x);
}

}

The call to mc.check() calls the main class's version of the method.

However, if I change the sub-class to:

class SubClass extends MainClass {

void check(Object x) {
System.out.println("Sub class: " + x);
}

}

then it uses the sub-class always.

Right. You've made the mistake (and you're not the first,
nor the last) of confusing overRIDING with overLOADING. In your
first example, the `check' method of SubClass does not override
the `check' method of MainClass; is is an overload (of the `check'
identifier). SubClass has two different methods named `check':

void check(String) ... // inherited
void check(Object) ... // defined locally

In your second example things are quite different: SubClass
has only one `check' method:

void check(Object) ... // overrides MainClass method

Note that this `check' has exactly the same signature as the
MainClass `check'; that's why it overrides. In your first example
the two `check' methods have different signatures and have nothing
to do with each other, as you may see by experimenting with

class HeroClass extends MainClass {
double check(short shrift, String along) ...
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,787
Messages
2,569,627
Members
45,329
Latest member
InezZ76898

Latest Threads

Top