Call method with implicit downcast - java

I have a List defined as
List<ParentClass> parentClassList;
Parent class is abstract, so when I add elements to the List I do something like
parentClassList.add(new ChildClassOne(...));
parentClassList.add(new ChildClassTwo(...));
and so on... I actually have 5 child classes right now.
What I'd like to do is to call a method in another Class, overwriting its arguments, so:
public void doSomething(ChildClassOne arg) {...}
public void doSomething(ChildClassTwo arg) {...}
But if the type of the List is the parent Class I can't do
doSomething(parentClassList.get(0));
Basically I need to perform different actions based on the child's type and I need access to all the methods inside a specific child. Different childs have different methods, they have only one methods in common.

Define an abstract emthod doSomthing() in ParentClass, and in each sub class you implement it like this:
class ChildClassOne {
void doSomething() {
instanceOfSomeOtherClass.doSomething(this); // will call the correct method
}
}
and SomeOtherClass will have methods for each sub class:
class SomeOtherClass {
void doSomething(ChildClassOne o) {};
void doSomething(ChildClassTwo o) {};
void doSomething(ChildClassThree o) {};
...
}
You can read about this approach in regards to the Visitor Pattern
It might be even simpler if you moved the code from SomeOtherClass into the ChildClasses, though.

In this situation a double dispatch technique called Visitor Pattern becomes very handy:
interface Visitor {
void visitChildOne(ChildOne child);
void visitChildTwo(ChildTwo child);
void visitChildThree(ChildThree child);
}
abstract class ParentClass {
public abstract void accept(Visitor v);
...
}
class ChildClassOne extends ParentClass {
#Override
public void accept(Visitor v) { v.visitChildOne(this); }
}
class ChildClassTwo extends ParentClass {
#Override
public void accept(Visitor v) { v.visitChildTwo(this); }
}
class ChildClassThree extends ParentClass {
#Override
public void accept(Visitor v) { v.visitChildThree(this); }
}
When you need to perform some task that does different things depending on the type of a child, provide an implementation of the Visitor interface, and pass it to accept of each of the children that you wish to process:
Visitor v = new Visitor() {
#Override
public void visitChildOne(ChildOne child) {
System.out.println("Visiting child type 1");
String someProperty = child.getPropertySpecificToChildOne();
}
#Override
public void visitChildTwo(ChildTwo child) {
System.out.println("Visiting child type 2");
int someProperty = child.getPropertySpecificToChildTwo();
}
#Override
public void visitChildThree(ChildThree child) {
System.out.println("Visiting child type 3");
}
};
for (Parent p: parentClassList) {
p.accept(v);
}

Basically I need to perform different actions based on the child's type and I need access to all the methods inside a specific child.
In this case the behavior you want to implement belongs into this specialized classes.
You might add another (abstract) method signature to the base class which you implement in the child classes providing the type depended behavior.

Related

Is there a way in Java to call different child method depending on which subclass is the object?

In my project I have a superclass and two subclasses extending from it. There is a method in the superclass that is overriden differently in each subclass.
I want to know if it's possible to introduce a method (in another class) that takes object of either subclass as a parameter and calls a method overriden in one of subclasses (depending on to which subclass does the object belong).
public class Superclass{
public int method(){return 0;}
}
public class Subclass1 extends Superclass{
public int method(){return 1;}
}
public class Subclass2 extends Superclass{
public int method(){return 2;}
}
public class CallingClass{
public static int dependantCall(Superclass parameter){return parameter.method}
I want to be able to do something like
Subclass1 subclassObject = new Subclass1;
System.out.println(CallingClass.dependantCall(subclassObject));
and get output
1
That is what Polymorphism is for! Defining the Superclass as a parameter type will allow you to pass either subclass in.
For example in your other class you can define it like this:
// classes Dog and Cat extend Animal and override makeNoise()
class Owner{
playWith(Animal a){
a.makeNoise();
}
}
Now the Owner can accept owner.makeNoise(cat) and owner.makeNoise(dog)
More reading: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Yes, it is entirely possible. Here's how that method would look like:
public <T extends Superclass> void foo(T subclassObject) {
...
}
Or:
public void foo(Superclass obj) {
...
}
Note that in the above method, you can pass subclasses' objects as well (they are covariant data types).
This is what Java does by default when you create subclases, so no need to do anything special. Each object carries it's type information at run time, and the method invoked would always be the most specific one for the object. Example:
public class Doer {
public void doSomething() {
// Body presence
};
}
public class Painter extends Doer {
#Override
public void doSomething() {
// Paint here
}
}
public class Manager extends Doer {
#Override
public void doSomething() {
// Micromanage here
}
}
// Elsewhere in your code:
public void busyness(Doer doer) {
doer.doSomething();
}
A style note: if it is possible, one should prefer using interfaces instead of base classes (base classes those should be used only if you want to share implementation between subclasses). Example with interfaces:
public interface Doer {
void doSomething();
}
public class JackOfAllTrades implements Does {
#Override
public void doSomething() {
// Do whatever necessary
}
}
// Client code stays exactly the same as above:
public void busyness(Doer doer) {
doer.doSomething();
}
Note that in Java a class can have only one base class but can implement multiple interfaces.
#Override annotations are not strictly required, but they help Java compiler to spot some errors for you (e.g. if you misprint method name).
In your example it would look like
public class CallingClass {
public static int dependantCall(Superclass parameter) {
return parameter.method();
}
}
Subclass1 subclassObject = new Subclass1();
System.out.println(CallingClass.dependantCall(subclassObject));

In Object Oriented theory, should a derived class inherit a parent object's Interface?

I'm a self taught hobbyist programmer and all my knowledge is derived from seeing what the compiler does and doesn't like.
Suppose I have (in C# notation, Java may have other abilities)
The class I need to override looks like this:
public interface ICanDoSomethingElse
{
void DoIt();
}
class Parent : ICanDoSomethingElse
{
public void EatTacos()
{
}
void ICanDoSomethingElse.DoIt(string thingToDo)
{
// Implementation
}
}
So I do this:
class Child : Parent, ICanDoSomethingElse
{
new public void EatTacos()
{
}
void ICanDoSomethingElse.DoIt(string thingToDo) // NEW keyword illegal here?
{
// Implementation
}
}
Question
I observe that the new keyword is illegal in the interface. Is that because this is an explicit Interface?
Is there any way to force children to implement an interface, or does that just mean I need to set up an implicit/explicit cast?
I observe that the new keyword is illegal in the interface. Is that because this is an explicit Interface?
The error is because you're implementing the interface explicitly in the classes.
Explicit implementaton forces the methods to be exposed only when you are working with the interface directly, and not the underlying implementation.
If your classes are like this:
class Parent : ICanDoSomethingElse
{
...
public void DoIt(string thingToDo)
{
// Implementation
}
}
class Child : Parent, ICanDoSomethingElse
{
...
public new void DoIt(string thingToDo)
{
// Implementation
}
}
You will need to use new keyword to somehow hide Parent.DoIt implementation.
Is there any way to force children to implement an interface, or does that just mean I need to set up an implicit/explicit cast?
You can make Parent class abstract, then the interface's methods abstract too:
abstract class Parent : ICanDoSomethingElse
{
...
public abstract void DoIt(string thingToDo);
}
class Child : Parent, ICanDoSomethingElse
{
...
public override void DoIt(string thingToDo)
{
// Implementation
}
}
Here, Child must implement DoIt method.
I think the interface implementation you're doing has nothing to do with the new keyword.
The new keyword is using when defining a new behavior on a method that is inherits from its parent
public class Parent{
public void SayHello(){
Console.WriteLine("Hello from parent");
}
}
And the child
public class Child : Parent {
public new void SayHello(){
Console.WriteLine("Hello from child");
}
}
If you want to use an interface as an implementation, you don't need to use new keyword

Overloading and Polymorphism

I wish someone would explain me how this decision was taken. I understand that, the overloaded version is chosen based on the declared type, but why, on the second call, the decision was taken based the runtime type?
public class Test {
public static void main(String[] args) {
Parent polymorphicInstance = new Child();
TestPolymorphicCall tp = new TestPolymorphicCall();
tp.doSomething(polymorphicInstance);
// outputs: Parent: doing something...
call(polymorphicInstance);
// outputs: Child: I'm doing something too
}
public static void call(Parent parent){
parent.doSomething();
}
public static void call(Child child){
child.doSomething();
}
}
public class Parent {
public void doSomething() {
System.out.println("Parent: doing something...");
}
}
public class Child extends Parent{
#Override
public void doSomething() {
System.out.println("Child: I'm doing something too");
}
}
public class TestPolymorphicCall {
public void doSomething(Parent p) {
System.out.println("Parent: doing something...");
}
public void doSomething(Child c) {
System.out.println("Child: doing something...");
}
}
Thanks in advance!
Your Parent class reference is referring to Child class object:
Parent polymorphicInstance = new Child();
So, when you pass the reference in call method, the actual method invoked is the one with Parent parameter type only. But when you call the method doSomething(), on parent reference:
public static void call(Parent parent){
parent.doSomething();
}
It will call doSomething() method, that you have overridden in Child class.
This is the classic case of polymorphism. Suppose you have a class Shape and a subclass Circle, which overrides the method calculateArea() defined in Shape class.
Shape circle = new Circle();
// This will invoke the method in SubClass.
System.out.println(circle.calculateArea());
When you override a super class method in subclass, then the actual method invoked is decided at runtime, based on what actual object your super class reference points to. This is called Dynamic Dispatch of method call.

Can you automatically cast an object of one class to a subclass and call an overloaded method in Java?

I have the following setup:
class Base {};
class ImplA extends Base {};
class ImplB extends Base {};
class ImplC extends Base {};
Base baseFactory(int type) {
switch(type) {
case 0:
return new ImplA();
case 1:
return new ImplB();
case 2:
return new ImplC();
}
Base a = baseFactory(0);
Base b = baseFactory(1);
Base c = baseFactory(2);
List<Base> list = new ArrayList<Base>();
list.add(a);
list.add(b);
list.add(c);
// Somewhere else I have:
interface BaseHandler {
process(ImplA a);
process(ImplB b);
process(ImplC c);
};
Now, what I would like to be able to do is something along the lines of:
class Processor {
BaseHandler bh;
Processor(BaseHandler bh) {
this.bh = b;
}
void processList(List<Base> list) {
for (Base x : list) {
bh.process(x);
}
}
And then have a user implement BaseHandler and be able to construct a Processor to operate on each element in the Base list.
But, this does not work as process(Base) is not defined. It may seem simple to just add 3 if statements, but I already have a switch like structure in building instances of classes extending the Base. It seems unnecessary to repeat this over and over. Is there a way to achieve this idea without writing an intermediate step that determines the runtime class of each Base in the list and calls the appropriate method (in effect another switch case -- but it would be if's)?
I think one work around idea would be to make each Base have an abstract process method which needs to be implemented by the Impl classes. However, this is not acceptable in my situation since the user will not be implementing the Impl classes. Basically, I need process to be a user-defined callback. Further, it does not make sense for process to be a member of the Impl or Base classes since it is in no way related. It's a separate callback that needs to respond dynamically to the type it is called with. And the type is always guaranteed to be a subclass of Base.
You do need the "intermediate step" that you describe, but it need not be if statements. What you're looking for is double dispatch using the visitor pattern. Basically your Base class would have a method:
void accept(BaseHandler handler);
and each subclass would implement it as:
handler.process(this);
where this would resolve to the correct type in each subclass at compile-time.
What you're looking for is the Visitor pattern. You put an abstract method on Base, but all it does is call the appropriate method in BaseHandler:
public interface Base {
void acceptHandler(BaseHandler handler);
}
Then your concrete implementations override acceptHandler and call the correct overload.
public class ImplA implements Base {
public void acceptHandler(BaseHandler handler) {
handler.process(this);
}
}
At this point there's not much value in the overloading, and you'd be better off just giving your methods descriptive names.
It sounds like what you want is the Visitor pattern here:
public interface BaseVisitor {
void caseA(ImplA a);
void caseB(ImplB b);
void caseC(ImplC c);
}
public class MyVisitor implements BaseVisitor {
void visit(List<Base> bases) {
for (Base b : bases) {
b.accept(this);
}
}
public void caseA(ImplA a) { // ... }
public void caseB(ImplB b) { // ... }
public void caseC(ImplC c) { // ... }
}
public abstract class Base {
abstract void accept(BaseVisitor visitor);
}
public class ImplA {
public void accept(BaseVisitor visitor) {
visitor.caseA(this);
}
}
public class ImplB {
public void accept(BaseVisitor visitor) {
visitor.caseB(this);
}
}
public class ImplC {
public void accept(BaseVisitor visitor) {
visitor.caseC(this);
}
}

Extending functionality of all implementations of an Interface?

I'm looking to create a set of functions which all implementations of a certain Interface can be extended to use. My question is whether there's a way to do this without using a proxy or manually extending each implementation of the interface?
My initial idea was to see if it was possible to use generics; using a parameterized type as the super type of my implementation...
public class NewFunctionality<T extends OldFunctionality> extends T {
//...
}
...but this is illegal. I don't exactly know why this is illegal, but it does sort of feel right that it is (probably because T could itself be an interface rather than an implementation).
Are there any other ways to achieve what I'm trying to do?
EDIT One example of something I might want to do is to extend java.util.List... Using my dodgy, illegal syntax:
public class FilterByType<T extends List> extends T {
public void retainAll(Class<?> c) {
//..
}
public void removeAll(Class<?> c) {
//..
}
}
You can achieve something like this using a programming pattern known as a 'decorator' (although if the interface is large then unfortunately this is a bit verbose to implement in Java because you need to write single-line implementations of every method in the interface):
public class FilterByType<T> implements List<T> {
private List<T> _list;
public FilterByType(List<T> list) {
this._list = list;
}
public void retainAll(Class<?> c) {
//..
}
public void removeAll(Class<?> c) {
//..
}
// Implement List<T> interface:
public boolean add(T element) {
return _list.add(element);
}
public void add(int index, T element) {
_list.add(index, element);
}
// etc...
}
Alternatively, if the methods don't need to access protected members, then static helper methods are a less clucky alternative:
public class FilterUtils {
public static void retainAll(List<T> list, Class<?> c) {
//..
}
public static void removeAll(List<T> list, Class<?> c) {
//..
}
}
What prevents you from just adding new methods to the interface?
If you can't just add the new functionality to old interface, you could consider making another interface and then an implementation which merely implements those two. Just to be clear, in code this is what I mean:
// Old functionality:
public interface Traveling {
void walk();
}
// Old implementation:
public class Person implements Traveling {
void walk() { System.out.println("I'm walking!"); }
}
// New functionality:
public interface FastTraveling {
void run();
void fly();
}
// New implementation, option #1:
public class SuperHero extends Person implements FastTraveling {
void run() { System.out.println("Zoooom!"); }
void fly() { System.out.println("To the skies!"); }
}
// New implementation, option #2:
public class SuperHero implements Traveling, FastTraveling {
void walk() { System.out.println("I'm walking!"); }
void run() { System.out.println("Zoooom!"); }
void fly() { System.out.println("To the skies!"); }
}
I think it's illegal because you can not guarantee what class T will be. Also there are technical obstacles (parent's class name must be written in bytecode, but Generics information get lost in bytecode).
You can use Decorator pattern like this:
class ListDecorator implements List {
private List decoratingList;
public ListDecorator(List decoratingList){
this.decoratingList = decoratingList;
}
public add(){
decoratingList.add();
}
...
}
class FilterByArrayList extends ListDecorator {
public FilterByAbstractList () {
super(new ArrayList());
}
}
There is a delegation/mixin framework that allows a form of this. You can define a new interface, implement a default implementation of that interface, then request classes which implement that interface but subclass from elsewhere in your hierarchy.
It's called mixins for Java, and there's a webcast right there that demonstrates it.
I'm afraid it's not clear what do you want to get.
Basically, I don't see any benefit in using 'public class NewFunctionality<T extends OldFunctionality> extends T' in comparison with 'public class NewFunctionality extends OldFunctionality' ('public class FilterByType<T extends List> extends T' vs 'public class FilterByType<T> implements List<T>')

Categories

Resources