Call unique methods without instanceof

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

31 Replies - 2456 Views - Last Post: 28 November 2012 - 08:05 PM Rate Topic: -----

#1 Virkin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 18
  • Joined: 14-June 12

Call unique methods without instanceof

Posted 27 November 2012 - 08:25 AM

Hello again programmers!

So I have a more design question and want your opinions on what is best to be done here.

Say I have three classes with simple inheritance. So in simple form -

public abstract class Base {}

public class DerivedOne extends Base {}

public class DerivedTwo extends Base {}


Now in another class I have an List<Base> objects which holds a load of random DerivedOne and DerivedTwo classes.

public class Client {
	List<Base> listBase = new ArrayList<Base>();
	// filled with lots of Base subclasses
}


For pretty much all operations this works fine as I override methods in DerivedOne and DerivedTwo.

However the problem comes when I add in method to DerivedTwo that is unique to just that one class like -

public class DerivedTwo extends Base {
	public void uniqueMethod() {}
}


Now in my Client class I need to provide a method to call this uniqueMethod on all DerivedTwo objects in the list.

I could

public void callAllUniqueMethods() {
	for(Base b : listBase) {
		if(b instanceof DerivedTwo)
			((DerivedTwo) B)/>.uniqueMethod();
	}
}


But I consider this pattern as I mess bade code design.

I could of course also have an abstract method in the Base class and override in each subclass. However that would
mean I would be leaving the method body empty in other implementations. It also messy to me.

I also thought have interface contining unique method and only implement interface on DeriveddTwo (there could be
more classes that have unique method) but not all. However again this approach have to have an instanceof and cast
to call the method.

So really what would you suggest in this situation?

Thanks again!

Is This A Good Question/Topic? 0
  • +

Replies To: Call unique methods without instanceof

#2 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,996
  • Joined: 20-September 08

Re: Call unique methods without instanceof

Posted 27 November 2012 - 09:02 AM

afaik, there's no practicable way. If you use the supertype then you generally do that when you don't need specialized subclass methods
Was This Post Helpful? 2
  • +
  • -

#3 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 8013
  • View blog
  • Posts: 13,719
  • Joined: 19-March 11

Re: Call unique methods without instanceof

Posted 27 November 2012 - 09:44 AM

*
POPULAR

You're right about one thing - that's terrible design. "instanceof" is a warning flag: it means you've broken your design. You could do this with reflection, but that would be just as bad, and for the same reason. OO design is supposed to make your life easier, and this is not doing that.

So when you have a list of Foo, you need to assume that everything in it is of type Foo, and can do exactly what Foos can do - nothing more! (as g00se has already said, in different words)

So what are the object oriented ideas here? Depends on what you're modeling. Let's suppose you're designing a class of objects which has subtypes. Those subtypes can either bar() or not, and if they bar(), then they do it in their own way. In that case, you could modify your base class to have an empty method slot for bar() and override it if it does something there.

For exmaple, the classic Animal hierarchy usually has Animals able to makeSound(). However, there are certainly animals which don't verbalize - most Fish, for example - so you'd probably have this implemented as an empty stub, which you'd fill in where appropriate.

The converse of this would be to include a default implementation of bar(), and override it as needed. As long as your design is aware that sometimes bar() will do nothing, then you're okay.

Maybe you can't modify the superclass. In that case, your best bet would be to extend it and build your hierarchy from there. You might want to think about using an interface to require that method instead, this might work better for you.

The main thing you want to keep in mind is that if you have an instance of a Foo, the things you can do with that instance are Foo things. Even if that Foo happens to be also a Bar, which extends Foo, or a Baz, which is an interface it implements, all you know about it is that it's a Foo, and that's all you can do with it. If your design requires something else, it's probably not a good design.
Was This Post Helpful? 5
  • +
  • -

#4 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8347
  • View blog
  • Posts: 31,910
  • Joined: 06-March 08

Re: Call unique methods without instanceof

Posted 27 November 2012 - 09:52 AM

View PostVirkin, on 27 November 2012 - 11:25 AM, said:

I could of course also have an abstract method in the Base class and override in each subclass. However that would
mean I would be leaving the method body empty in other implementations.


Why making it abstract ?
Make it not abstract doing nothing in the super class.
The sub classes that want to overload it will just have to overload it.
Was This Post Helpful? 2
  • +
  • -

#5 Virkin  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 18
  • Joined: 14-June 12

Re: Call unique methods without instanceof

Posted 27 November 2012 - 10:00 AM

Haha I somehow not even think about leaving it empty in the superclass and overriding where appropriate. Thanks again :)
Was This Post Helpful? 0
  • +
  • -

#6 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,996
  • Joined: 20-September 08

Re: Call unique methods without instanceof

Posted 27 November 2012 - 02:17 PM

Quote

Haha I somehow not even think about leaving it empty in the superclass and overriding where appropriate. Thanks again :)
No that doesn't cut it either unfortunately. Using that approach:

a. every single specialized method would have to be declared in the base class. That is actually tantamount to negating the entire concept of specialization in polymorphism.
b. every single child abstraction (class) is going to be forced to deal with every single abstract method, even if they have no useful connection with it now nor ever will have
Was This Post Helpful? 1
  • +
  • -

#7 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 8013
  • View blog
  • Posts: 13,719
  • Joined: 19-March 11

Re: Call unique methods without instanceof

Posted 27 November 2012 - 02:28 PM

View Postg00se, on 27 November 2012 - 04:17 PM, said:

Quote

Haha I somehow not even think about leaving it empty in the superclass and overriding where appropriate. Thanks again :)/>/>
No that doesn't cut it either unfortunately. Using that approach:

a. every single specialized method would have to be declared in the base class. That is actually tantamount to negating the entire concept of specialization in polymorphism.
b. every single child abstraction (class) is going to be forced to deal with every single abstract method, even if they have no useful connection with it now nor ever will have



a. No, only the methods that every instance of this base class is expected to have. And that's what we want, isn't it?
b. No, since they won't be abstract.

Remember the purpose of this: we wanted to be able to put subclasses in a collection of Superclass and call methods on them. Either we have to use the instanceof/cast formulation, or we have to know that the methods are available.

As I said, perhaps an interface is the better option, but one way or another the subclasses need to inherit the required methods.

This post has been edited by jon.kiparsky: 27 November 2012 - 02:38 PM

Was This Post Helpful? 1
  • +
  • -

#8 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,996
  • Joined: 20-September 08

Re: Call unique methods without instanceof

Posted 27 November 2012 - 02:32 PM

Quote

a) No, only the methods that every instance of this base class is expected to have. And that's what we want, isn't it?

No, the OP's purpose is to be able to contain, tidily, any subclass of the base class in a List whose contained type is the base class AND to be able to call (again conveniently) any specialized method in a subclass. That's kind of ... the opposite ;)/>

This post has been edited by g00se: 27 November 2012 - 02:32 PM
Reason for edit:: typo

Was This Post Helpful? 0
  • +
  • -

#9 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 8013
  • View blog
  • Posts: 13,719
  • Joined: 19-March 11

Re: Call unique methods without instanceof

Posted 27 November 2012 - 02:46 PM

That was the original requirement, but of course that's the opposite of object-oriented design. So the requirement had to be repaired, since it made no sense as originally stated.


Actually, there's another way you could do this, also pretty awful, and also requiring one change to the base class. And that would be to have a base class method called "doUniqueMethod" or something like that, and then use that to call the method (if any) that's required.


So there's always another way, but usually if you get into this kind of trouble it's because you're trying to do things that don't make sense. Classes group functionality in Java: if you have a list of objects of type Superclass, all you really know about them is they can perform the operations defined by Superclass. You know nothing about the implementations provided by Subclass, and you know nothing about extra methods provided by Subclass.
Was This Post Helpful? 0
  • +
  • -

#10 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,996
  • Joined: 20-September 08

Re: Call unique methods without instanceof

Posted 27 November 2012 - 02:51 PM

Quote

So the requirement had to be repaired, since it made no sense as originally stated.
Indeed it had to be repaired. I was just pointing out that pushing all methods up as abstract into the base class is not a solution

Quote

And that would be to have a base class method called "doUniqueMethod" or something like that, and then use that to call the method (if any) that's required.
How? Reflection? ;)

This post has been edited by g00se: 27 November 2012 - 02:52 PM

Was This Post Helpful? 0
  • +
  • -

#11 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 8013
  • View blog
  • Posts: 13,719
  • Joined: 19-March 11

Re: Call unique methods without instanceof

Posted 27 November 2012 - 02:57 PM

No, god no. By override in the subclass. So doUniqueMethod does nothing by default, or it calls whatever method you specify. Or it prints "booga booga ha ha ha!" to the command line, or it curls War and Peace from gutenberg.org and bubblesorts it. So really, not a great solution, as I said - but it's a way to do something like what was requested.
Was This Post Helpful? 0
  • +
  • -

#12 g00se  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 2831
  • View blog
  • Posts: 11,996
  • Joined: 20-September 08

Re: Call unique methods without instanceof

Posted 27 November 2012 - 03:01 PM

Yes, i see what you mean but i suspect you're right about it being a bad idea
Was This Post Helpful? 0
  • +
  • -

#13 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 8013
  • View blog
  • Posts: 13,719
  • Joined: 19-March 11

Re: Call unique methods without instanceof

Posted 27 November 2012 - 03:10 PM

I agree with your suspicions. :)
At this point, I'm just brainstorming ways to get what was asked for, trying to disprove my hypothesis that there isn't a way to do this outside of ordinary inheritance.
Was This Post Helpful? 0
  • +
  • -

#14 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5932
  • View blog
  • Posts: 12,857
  • Joined: 16-October 07

Re: Call unique methods without instanceof

Posted 27 November 2012 - 03:16 PM

The Base class you want is already written, it's called Object. :P

Of course, this is all making little sense since we can't see how you intend to fit your hierarchical mess together. A base class offers shared functionality that the children extend. However, if they don't really extend anything, then you probably just want a wrapper or something.

I suppose you could have some wonky container object with a variable to hold each instance. Or perhaps some kind of interface or method registry. Again, still not good ideas, but it's hard to solve the problem when we can't see the attempt.
Was This Post Helpful? 0
  • +
  • -

#15 cfoley  Icon User is offline

  • Cabbage
  • member icon

Reputation: 2069
  • View blog
  • Posts: 4,307
  • Joined: 11-December 07

Re: Call unique methods without instanceof

Posted 27 November 2012 - 04:05 PM

This sounds like it might be a case for the visitor pattern.

All cats can purr.
Tigers can also roar.
Kittens don't roar but they often meow when they should be purring.

Consider a pet shop (before the days of health and safety gone mad) stocking cats, tigers and kittens that lets you play with the pets. You can imagine a loop for playing with the cats, provoking various sounds.

The idea is to have a general play method that works for each kind of cat that needs to be treated differently. In this case, it is Cat and Tiger. Kittens can just be treated like the base case Cat. Then you have a method in Cat and Tiger that accepts the PetShop (i.e. the visitor) and calls the appropriate method. This is what it all looks like:

public interface CatVisitor {
	public void visit(Cat c);
	public void visit(Tiger t);
}

public class PetShop implements CatVisitor {
	
	public static void main(String[] args) {
		PetShop shop = new PetShop();
		shop.playWithAll();
	}
	
	private Collection<Cat> cats;
	
	public PetShop() {
		cats = new ArrayList<>();
		cats.add(new Cat());
		cats.add(new Tiger());
		cats.add(new Kitten());
	}
	
	public void playWithAll() {
		for(Cat c : cats) {
			c.accept(this);
			System.out.println();
		}
	}

	@Override
	public void visit(Cat c) {
		c.purr();
	}

	@Override
	public void visit(Tiger t) {
		t.purr();
		t.roar();
	}
	
}

public class Cat {
	public void purr() {
		System.out.print("purr ");
	}
	
	public void accept(CatVisitor v) {
		v.visit(this);
	}
}

public class Tiger extends Cat {
	public void roar() {
		System.out.print("roar ");
	}
	
	@Override
	public void accept(CatVisitor v) {
		v.visit(this);
	}
}

public class Kitten extends Cat {
	@Override
	public void purr() {
		System.out.print("meow purr meow");
	}
}


The output is:

Quote

purr
purr roar
purr meow purr


So, here we have a sledgehammer cracking a nut. It's loads of code for what it does. A better example is saving objects. In principle, every object in a hierarchy could have a save method and a load method. But should they all have saveXml(), saveCsv(), saveJavaSerialized(), saveTxt(), etc... and all the corresponding load methods? What happens when you want to add HTML. In the visitor pattern, you have one accept() method and separate visitors for saving each file type, and more visitors for loading each file type.

Again, loads of code especially for this trivial example but it gets around the design problems and uses a well-known and easily-recognisable pattern.
Was This Post Helpful? 1
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3