Avoiding polymorphism in Java

Started by
4 comments, last by Telastyn 12 years, 3 months ago
Is there a way I can explicitly avoid polymorphism is Java? For example, in the following code:

public class Main
{
public static void main(String[] args)
{
new Main().Run();
}
public void Run()
{
ClassB b = new ClassB();
b.doThing();
}
public class ClassA
{
public void doThing()
{
print();
}
public void print()
{
System.out.println("A");
}
}
class ClassB extends ClassA
{
public void print()
{
System.out.println("B");
}
}
}


Is there anyway I can write doThing() so that it always calls the ClassA version of print so that when the program runs it prints “A” instead of “B”
-----------------------------Download my real time 3D RPG.
Advertisement
Why would you want to?

In general, if you run into this sort of thing where it's hard to do something in the language, it's a hint not to do that.

Why would you want to?

In general, if you run into this sort of thing where it's hard to do something in the language, it's a hint not to do that.


Polymorphism caused a problem in one of my programs when a constructor called the wrong function. I've settled the problem, but I would like to be able to avoid in the future.
-----------------------------Download my real time 3D RPG.
Depending on what you mean, [font=courier new,courier,monospace]final[/font]?
[TheUnbeliever]

Is there a way I can explicitly avoid polymorphism is Java? For example, in the following code:

public class Main
{
public static void main(String[] args)
{
new Main().Run();
}
public void Run()
{
ClassB b = new ClassB();
b.doThing();
}
public class ClassA
{
public void doThing()
{
print();
}
public void print()
{
System.out.println("A");
}
}
class ClassB extends ClassA
{
public void print()
{
System.out.println("B");
}
}
}


Is there anyway I can write doThing() so that it always calls the ClassA version of print so that when the program runs it prints “A” instead of “B”


no, you cannot. You will brake LSP (Liskov substitution principle)


[quote name='Telastyn' timestamp='1325713684' post='4899714']
Why would you want to?

In general, if you run into this sort of thing where it's hard to do something in the language, it's a hint not to do that.

do you know how using

Polymorphism caused a problem in one of my programs when a constructor called the wrong function. I've settled the problem, but I would like to be able to avoid in the future.
[/quote]

post an example of that constructor issue... do you remember how constructors works with subclassing and the role of the "super" keyword?

[quote name='Telastyn' timestamp='1325713684' post='4899714']
Why would you want to?

In general, if you run into this sort of thing where it's hard to do something in the language, it's a hint not to do that.


Polymorphism caused a problem in one of my programs when a constructor called the wrong function. I've settled the problem, but I would like to be able to avoid in the future.
[/quote]

How'd you settle the problem?

By not calling functions of anything but parameters in the constructor (or eliminating the need in your design)? Good, avoid it in the future by following that general rule.

post an example of that constructor issue... do you remember how constructors works with subclassing and the role of the "super" keyword?



The problem was that the overwriting function was using objects in the the derived class before they had a chance to initialize. I used a null check to solve it. It was a simple fix, but I just thought it might be useful to know how to explicitly choose which version to use just in case a more complex situation arises.
-----------------------------Download my real time 3D RPG.

The problem was that the overwriting function was using objects in the the derived class before they had a chance to initialize. I used a null check to solve it.

While that may work well enough for your current needs, calling polymorphic functions from base class constructors is generally a crappy idea, precisely for the reason you have stated: the derived class will not yet be initialised when the method is called.

If you can't avoid this practice entirely, make sure you document that the functions must check for class initialisation - otherwise you or some other programmer is likely to run afoul of the issue a year or two down the line...

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Sounds like a poor abstraction was the root of your constructor problem. Inheritance is an appropriate tool is LSP is upheld.

throw table_exception("(? ???)? ? ???");

Inheritance is the deepest coupling between classes. When modifying the child or parent classes, you must be aware of the implications across this inheritance hierarchy.

For some problems, an alternative solution can be to break the polymorphic aspects of the class into a separate interface. This way, there is no requirement for the implementor to extend your class - they can just plug in another class that implements the polymorphic behaviour.

As mentioned, using the final keyword can help by allowing the base class designer to specify which functions are designed to be overridden.


The problem was that the overwriting function was using objects in the the derived class before they had a chance to initialize. I used a null check to solve it. It was a simple fix, but I just thought it might be useful to know how to explicitly choose which version to use just in case a more complex situation arises.
[/quote]
Adding a null check sounds brittle, I wouldn't recommend it.

This is another solution:

public class Parent {

public Parent() {
doFoo();
}

private void doFoo() {
// parent logic...
}

public void foo() {
doFoo();
}

}

public class Child extends Parent {

@Override
public void foo() {
// child logic...
}

}

This topic is closed to new replies.

Advertisement