The following code is the solution code, which declares an abstract class with one absract subclass (that in turn has two subclasses) and another subclass. Because the method setScore() has to be implemented in three different ways, and the objecttype differs for each case, I'm presuming we use the parameter P to define it.
public abstract class Vak<P> implements EvaluatieSpecificatie,
Comparable<Vak> {
private VakInfo vak;
public abstract void setScore(P parameter);
public Vak(VakInfo v) {
vak = v;
}
public String getVakNaam() {
return vak.getNaam();
}
public int getStudiepunten() {
return vak.getStudiepunten();
}
public String getVakcode() {
return vak.getVakcode();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(vak);
if (isGeslaagd()) {
sb.append(" C");
} else {
sb.append(" niet geslaagd - moet hernomen worden");
}
return sb.toString();
}
#Override
public int compareTo(Vak v) {
// sorteren van vakken op basis van studiepunten
// this < v --> neg waarde teruggeven
// this > v --> pos waarde teruggeven
// this = v --> 0 teruggeven
return this.getStudiepunten() - v.getStudiepunten();
}
}
Now, what I don't understand is how exactly this class ClassName"<"Parameter">" thing works, when to use it, or what exactly its called. I've tried to look it up, but I can't seem to find any information on it. Could anyone explain to me what exactly this is, and how/when it's supposed to be used? (Or link me in the right direction), perhaps by giving a simple example (since I'm not sure if asking for code is required).
I'm terribly sorry if this question isn't appropriate, but I'd really like to understand, so here goes.
Appereantly it's called a generic type. Thank you #HRgiger.
https://docs.oracle.com/javase/tutorial/java/generics/types.html
Related
I found that this worked :)
I found a way to make it work. Instead of this:
for(int i=0; i<alla.size(); i++){
if(alla.get(i).getClass().getName().equals("Aktie")){
alla.get(i).setKurs(0.0);
}
}
I got this to work:
for(Värdesak v : alla){
if(v instanceof Aktie){
((Aktie)v).setKurs(0.0);
}
}
I can't to figure out whats wrong with this one.. I have an arraylist of different objects, and I have a button in my program that is called "stock market crash" which should set all existing stocks course(have no clue what word i'm looking for here) in my arraylists to 0.0. shouldn't it be like this alla.get(i).setKurs(0.0); when I've found one stock object in my arraylist if the stock class (which is a subclass) have an public void setKurs(double kurs) { this.kurs = kurs; }?
I'll post my code here:
This is my button
class börsLyssna implements ActionListener{
public void actionPerformed(ActionEvent ave){
for(int i=0; i<alla.size(); i++){
if(alla.get(i).getClass().getName().equals("Aktie")){
alla.get(i).setKurs(0.0);
}
}
}
}
__
abstract class Värdesak{
private String namn;
protected Värdesak(String namn){
this.namn = namn;
}
public String getNamn(){
return namn;
}
abstract public double getVärde();
public String toString(){
return namn + ", "+ "värde: "+(getVärde()*1.25);
}
}
class Aktie extends Värdesak{
private int antal;
private double kurs;
public Aktie(String namn, int antal, double kurs){
super(namn);
this.antal = antal;
this.kurs = kurs;
}
public double getVärde(){
return (antal*kurs);
}
public String toString(){
return super.toString()+", antal: "+antal+" med en kurs på: "+kurs;
}
public void setKurs(double kurs) {
this.kurs = kurs;
}
public double getKurs() {
return kurs;
}
}
I believe that the (Class).getName() method returns the fully qualified class name (including the package).
For example, from the JDK 1.8 docs, the getName() comments contains this example:
String.class.getName()
returns "java.lang.String"
You're testing for the Class name without the package hierarchy preface.
Instead of
alla.get(i).getClass().getName().equals("Aktie")
try
alla.get(i) instanceof Aktie
The alla.get(i).getClass().getName() will return the package and name of the class, e.g. java.lang.String instead of just String.
Since you don't show us how alla is populated we can't tell if any Akties are even in it. There are a lot of suggested ways to fix this. Here's some debugging code that will let you clearly know where the problem is and when it's fixed.
class börsLyssna implements ActionListener{
public void actionPerformed(ActionEvent ave){
for(int i=0; i<alla.size(); i++){
if(alla.get(i).getClass().getName().equals("Aktie")){
System.out.println("Attempting to set kurs to 0.0 at i=" + i");//TODO remove debugging code
alla.get(i).setKurs(0.0);
}
}
}
}
Personally I think alla.get(i) instanceof Aktie will fix it. Though I think your life will be easier if you didn't put different types of objects in a collection in the first place. Wouldn't it be nice if you could just call set() on everything in there?
Let's say we have to check some set of rules before adding a new element in a collection. Elements are objects of a few similar types. All type specific features are encapsulated in subclasses of an abstract class. Collection contains objects of this abstract class. The rules apply conditions for types along with other constraints. For that reason the abstract superclass of items has additional type code. New element can be added to collection but due to additional rules other elements in collection can be removed or replaced.
In the code that needs to be refactored, validation of the rules is implemented as one long block of code with nested control flow statements. Validation of the type code breaks encapsulation. Separate branches of the control flow statements cannot be defined as method of corresponding subclasses of collection elements because them need to check type and make changes to collection.
additional facts regarding type code in my case:
type code does not affect the behaviour of class
type code is immutable
type code is used by ItemsManager to resolve some rules before to add
new element to collection.
How to eliminate type code and separate rules from types?
Here is example of such problem:
Type specific features of Items are encpsulated in AbstractItem subclasses.add method of ItemManager class breaks encapsulation.Rule: item of Type2 must be removed if new item of Type1 with the same value of SomeUsefull property is adding to collection.
For simplicity implementation of ICloneable and IComparable interfaces is omitted. In real world items in collection are immutable and cloneable and the system of rules is quite tangled.
abstract class AbstractItem {
private int Type; // this would like to eliminate
private int SomeUseful;
protected AbstractItem(int Type, int Value) {
this.Type = Type;
this.SomeUseful = Value;
}
public int getType() { return this.Type; }
public int getSomeUseful() { return this.SomeUseful; }
#Override
public String toString() {
return String.format("Item{Type=%d, Value=%d}", Type, SomeUseful);
}
}
class ItemType1 extends AbstractItem {
ItemType1(int Value) { super(1, Value); }
}
class ItemType2 extends AbstractItem {
ItemType2(int Value) { super(2, Value); }
}
class ItemManager {
private java.util.ArrayList<AbstractItem> ListOfItems;
public ItemManager(){
this.ListOfItems = new java.util.ArrayList<AbstractItem>();
}
public void add(final AbstractItem newItem) {
// this code breaks encapsulation
switch (newItem.getType()) {
case 1:
// do some type dependent operations
for(AbstractItem i: this.ListOfItems) {
if (i.getType()==2 && i.getSomeUseful()==newItem.getSomeUseful()) {
this.ListOfItems.remove(i);
break;
}
}
break;
case 2:
// do some other type dependent operations
break;
default:
// throw error
}
this.ListOfItems.add(newItem);
}
#Override
public String toString() {
String str = String.format("ItemsManager content");
for(AbstractItem i: this.ListOfItems) {
str += String.format("\n\tType = %d, Value = %d", i.getType(), i.getSomeUseful());
}
return str;
}
}
public class Example1 {
public static void main(String[] arg) {
System.out.println("Example 1");
ItemManager im = new ItemManager();
im.add(new ItemType1(1));
im.add(new ItemType2(2));
im.add(new ItemType2(3));
im.add(new ItemType1(3));
System.out.println(im.toString());
}
}
/*
Example 1
ItemsManager content
Type = 1, Value = 1
Type = 2, Value = 2
Type = 1, Value = 3
*/
Starting from #dbugger's answer you can push it further.
You can use Double Dispatch to hide the type code. Still not a perfect solution because the parent knows too much about its children, but the type code is gone now.
It is hard to tell what a better solution might be with the example code you have given, because when you simplified, you removed all the information about the items involved. There might be something there that could be used for discrimination in some other way, allowing you to get rid of the double dispatch with shoudBeRemovedBecauseType1.
Here is the altered onAdd method from type 1
#Override
public List<AbstractItem> onAdd(List<AbstractItem> list) {
for (AbstractItem item : list) {
if (item.shoudBeRemovedBecauseType1(this)) {
list.remove(item);
break;
}
}
return list;
}
A new method in the base class
public boolean shoudBeRemovedBecauseType1(ItemType1 itemType1)
{
return false;
}
overridden in the type 2 subclass
#Override
public boolean shoudBeRemovedBecauseType1(ItemType1 itemType1)
{
return getSomeUseful() == itemType1.getSomeUseful();
}
It's not ideal, but it's a step towards getting some encapsulation and killing the switch statement...
add an onAdd method to the base class that takes the list as a parameter.
public java.util.ArrayList<AbstractItem> onAdd(java.util.ArrayList<AbstractItem> list) { return list; }
then override it in the sub classes, for example...
#Override
public java.util.ArrayList<AbstractItem> onAdd(java.util.ArrayList<AbstractItem> list) {
for(AbstractItem i: this.ListOfItems) {
if (i.getType()==2 && i.getSomeUseful()==this.getSomeUseful()) {
list.remove(i);
break;
}
}
return list;
}
then rewrite the ItemManager add method to just call the sub classes' onAdd methods...
public void add(final AbstractItem newItem) {
this.ListOfItems = newItem.onAdd(this.ListOfItems);
this.ListOfItems.add(newItem);
}
I'm stuck with a problem here. I want to change the setter from a attribute from the superclass (parent class) in my subclass (child) however when I overide this method in my subclass I can't access my private attributes from the supperclass. And the point is, they have to stay private.
Superclass (problem: setMinimumVoorraad(int voorraad);)
package domein;
public abstract class Artikel implements Weegbaar
{
private String omschrijving;
private double prijs;
private int aantalInStock;
private int minimumVoorraad;
public Artikel(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad)
{
this.setOmschrijving(omschrijving);
this.setPrijs(prijs);
this.setAantalInStock(aantalInStock);
this.setMinimumVoorraad(minimumVoorraad);
}
#Override
public String toString()
{
String output = String.format(" \n omschrijving: %s \n prijs: %f \n In stock %d (minimumvoorraad = %d) \n", this.omschrijving, this.prijs, this.aantalInStock, this.minimumVoorraad);
return output;
}
//----Getters----
public String getOmschrijving() {
return omschrijving;
}
public double getPrijs() {
return prijs;
}
public int getAantalInStock() {
return aantalInStock;
}
public int getMinimumVoorraad() {
return minimumVoorraad;
}
//----Setters----
public void setOmschrijving(String omschrijving) {
this.omschrijving = omschrijving;
}
public void setPrijs(double prijs) {
this.prijs = prijs;
}
public void setAantalInStock(int aantalInStock) {
this.aantalInStock = aantalInStock;
}
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 2)
this.minimumVoorraad = 3;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Subclass
package domein;
public class Food extends Artikel
{
private String houdbaarheidsDatum;
private double nettoGewicht;
public Food(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad, String houdbaarheidsDatum, double nettoGewicht)
{
super(omschrijving, prijs, aantalInStock, minimumVoorraad);
this.setHoudbaarheidsDatum(houdbaarheidsDatum);
this.setNettoGewicht(nettoGewicht);
}
#Override
public boolean isWeegbaar()
{
return true;
}
//----Getters----
public String getHoudbaarheidsDatum() {
return houdbaarheidsDatum;
}
public double getNettoGewicht() {
return nettoGewicht;
}
//----Setters----
public void setHoudbaarheidsDatum(String houdbaarheidsDatum) {
this.houdbaarheidsDatum = houdbaarheidsDatum;
}
public void setNettoGewicht(double nettoGewicht) {
this.nettoGewicht = nettoGewicht;
}
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 5)
this.minimumVoorraad = 6;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Someone who can help me?
Thanks in advance.
One possibility is to implement the subclass's setter in terms of the superclass's setter (which, presumably, you do have access to).
For example, assuming the setter is setFoo, then the subclass's version might be:
public void setFoo(Foo f) {
// Do subclass stuff pre-setting, if any
super.setFoo(f);
// Do subclass stuff post-setting, if any
}
The answer given above by NPE is absolutely the best way to go about solving this problem. It is elegant and honors basic inheritance contracts between superclass and subclass. Even in your original post, the subclass is actually more restrictive than the superclass, so doing something like:
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad <= 5)
super.setMinimumVoorraad(6);
else
super.setMinimumVoorraad(minimumVoorraad);
}
exactly as NPE suggested would probably work. (Note how I modified your if test. Not sure if it's a typo, but in the original implementation 5 would be a valid minimum, but input like 4 would set it to 6.)
Other (possibly acceptable) patterns would be to:
Make the members in your Parent class protected, which would give visibility. (Realize that you did mention a private restriction; this pattern is solely mentioned to provide a more complete overall answer.)
Delegate the validation logic to another method (that is non-private). This way the child can override the validation method.
And now on to the (probably unacceptable) pattern of using Java reflection:
#Override
public void setMinimumVoorraad(int minimumVoorraad) {
try {
Field field = this.getClass().getSuperclass().getDeclaredField("minimumVoorraad");
field.setAccessible(true);
if(minimumVoorraad <= 5)
field.set(this, 6);
else
field.set(this, minimumVoorraad);
field.setAccessible(false);
}
catch(NoSuchFieldException | IllegalAccessException e) {
// do something
}
}
It's worth noting that if you never ever do this in your entire life you will probably be the better for it. Not only does it completely break all contracts, but it relies on hard-coded Strings to do field name lookups, which in and of itself is pretty painful. But it does exist. And no good answer (already given above by NPE) would be complete without an example of how not to do something...
I'm trying to make a class implement an interface correctly but seem to have hit a brick wall. I am not sure if the code I have already written is correct but it was the only way I understood how to approach the task. I have been given an interface with this information:
package mvcchords;
public interface NoteStore {
int getNextNote();
boolean hasNextNote();
void noteAdded(int midicode);
void start(int sortOrder);
}
The application displays piano keys which allow the user to click on them, and it saves the order they were clicked and the midicode of the notes for the specific sound. Then when the user clicks play, it recalls the tune in the order the notes were saved. When a user clicks on a note noteAdded is called. hasNextNote is used to check if it is the end of the saved notes or not. getNextNote is used to get the next note from the array list and start is called when the user clicks the play button. I have been told the integer sortOrder is irrelevant for this part of the task. I have been told that when the play button is clicked it should call the start method and then repeatedly call the getNextNote method until all the notes have been retrieved.
Below is the code I have written so far for a class to implement this interface;
import java.util.*;
import mvcchords.*;
public class MyNoteStore implements NoteStore {
public ArrayList<Integer> Notes;
public void noteAdded(int midicode) {
Notes.add(midicode);
}
public boolean hasNextNote(int k) {
if(Notes.get(k) != null)
return true;
else
return false;
}
public int getNextNote(int k) {
if(hasNextNote(Notes.get(k)) == true)
return Notes.get(k);
else
return 0;
}
public void start(int sortOrder) {
for(int k = 0; k < Notes.size(); k++){
hasNextNote(k);
getNextNote(k);
}
}
}
This code gives me an error saying
MyNoteStore is not abstract and does not override abstract method `hasNextNote()` in `mvcchords.NoteStore`.
I don't know where to go from here and any help would be appreciated. If further information is needed then I will do my best to clarify any points I have made.
Thank you in advance :)
While you have created methods with the correct names you need to have the correct parameters and return types as well. So in this case you need to alter:
int getNextNote(int i);
boolean hasNextNote(int k);
to remove the integer parameters.
Basically you need to keep track of the notes played back so far in the class so that you don't need to pass an integer about all the time. You could either use an Iterator or just store a integer to track the last index played. The below method uses an iterator, maybe you should try and create the one with an integer yourself.
public class MyNoteStore implements NoteStore {
ArrayList<Integer> notes = new ArrayList<Integer>();
Iterator<Integer> playbackIter;
public void noteAdded(int midicode) {
notes.add(midicode);
}
public boolean hasNextNote() {
if (playbackIter != null) {
return playbackIter.hasNext();
}
else {
return false;
}
}
public int getNextNote() {
if (playBackIter != null) {
return playBackIter.next();
}
else {
return -1;
}
}
public void start(int sortOrder) {
playBackIter = notes.iterator();
while(hasNextNote()) {
int note = getNextNote();
//play note
}
}
}
The parameters in the method are different between your implementation and the declaration in the interface.
Well,
your interface defines the methods:
int getNextNote();
boolean hasNextNote();
void noteAdded(int midicode);
void start(int sortOrder);
So,
your class has to implement them with the exact definition, which means with the same return type AND parameters. So you can either change them in the interface declaration or in the class implementation.
What is the difference between applying the visitor design pattern to your code and the following approach:
interface Dointerface {
public void perform(Object o);
}
public class T {
private Dointerface d;
private String s;
public String getS() {
return s;
}
public T(String s) {
this.s = s;
}
public void setInterface(Dointerface d) {
this.d = d;
}
public void perform() {
d.perform(this);
}
public static void main(String[] args) {
T t = new T("Geonline");
t.setInterface(new Dointerface() {
public void perform(Object o) {
T a = (T)o;
System.out.println(a.getS());
}
});
t.perform();
}
}
I assume that by using interfaces, we're not really separating the algorithm.
There is quite a big difference.
The visitor pattern uses interfaces, but its purpose is to be able to perform an operation to one or more classes (who implement an interface) without having to change the classes. Hence, the implementation actually "visits" the class and does its thing without the class being modified.
An interface is a basic concept used to provide a common API to a potentially diverse group of classes. The typical test for an interface is that classes that share it are alike in at least that one respect (is-like-a) and in those cases can be treated as such.
Here is a simple example on wikipedia that shows a couple of visitors in java.
Two things:
In your example you need two methods. The perfom and the setInterface. With a visitor pattern you would only need one method, the perfom, usually called accept.
If you need more than one 'performer', you will have to set the performer -via the setInterface method- for each. This makes it impossible to make your class immutable.
The most important difference in these examples is that in the visitor case you retain the compile-time concrete type of "this". This allows you to use double dispatch, where the method to be called is dependent on both the concrete data type and the visitor implementation. Double dispatch is just a special case of multiple dispatch where the method invoked is dependent on the receiver and the types of the parameters to the method. Java is of course single dispatch but some other languages support multiple dispatch.
The basic driving force behind the visitor pattern is that by using interfaces on the concrete nodes, every operation that needs to be added to a composite data structure must change every node. The visitor pattern uses a generic (static) pattern on the nodes so that dynamically adding operations is easy. The downside is that modifying the data structure (by adding or removing concrete nodes) becomes more difficult as all operation visitors are affected.
In general, this trade=off is a better match as it's more frequent to extend operations over a data structure than to change the data structure itself. Here's a lengthier writing of mine on how to use visitors and a bunch of considerations:
http://tech.puredanger.com/2007/07/16/visitor/
You might fairly ask if there is a pattern that allows us to do both: add operations or extend our data structures without breaking existing code. This is known as The Expression Problem as coined by Philip Wadler. You can find some links on this and more here:
http://tech.puredanger.com/presentations/design-patterns-reconsidered
A Visitor pattern is used when you have a data structure made up of many different classes and you have multiple algorithms that require a different operation for each class. In your example your DoInterface implementation only does one operation on one type. The only thing you do is print the result of getS() and because you cast o to T you can only do this to classes of type T.
If you wanted to apply your interface to a typical visitor style class you your the class with your DoInterface.perform function would likely end up with a big if else if statement in it something like this:
public void visit(Object o) {
if (o instanceof File)
visitFile((File)o);
else if (o instanceof Directory)
visitDirectory((Directory)o);
else if (o instanceof X)
// ...
}
Because this uses Object it will allow callers with any type which can create errors which will only show up at runtime. A Visitor gets around this by creating a “visitType” function for each type in the data structure. The classes in the data structure are then responsible for knowing which function on the visitor to call. The mapping is performed by each of the data structure’s classes implementing an accept function that then calls back on the Visitor class. If the function for the type does not exist on the visitor you get a compile error. The accept method looks like this:
#Override
public void accept(FileSystemVisitor v) {
v.visitFile(this);
}
Part of the trouble with the Visitor pattern is that it takes quite a lot of code to really do it justice in a sample. I think this is why a lot of people don't get it as it is easy to get distracted by the other code. I have created a simple file system sample that hopefully shows how to use a visitor more clearly. It creates a composite with some files and directories in and then performs two operations on the hierarchy. In practice you would probably want more than two data classes and two operations to justify this pattern but this is only an example.
public class VisitorSample {
//
public abstract class FileSystemItem {
public abstract String getName();
public abstract int getSize();
public abstract void accept(FileSystemVisitor v);
}
//
public abstract class FileSystemItemContainer extends FileSystemItem {
protected java.util.ArrayList<FileSystemItem> _list = new java.util.ArrayList<FileSystemItem>();
//
public void addItem(FileSystemItem item)
{
_list.add(item);
}
//
public FileSystemItem getItem(int i)
{
return _list.get(i);
}
//
public int getCount() {
return _list.size();
}
//
public abstract void accept(FileSystemVisitor v);
public abstract String getName();
public abstract int getSize();
}
//
public class File extends FileSystemItem {
//
public String _name;
public int _size;
//
public File(String name, int size) {
_name = name;
_size = size;
}
//
#Override
public void accept(FileSystemVisitor v) {
v.visitFile(this);
}
//
#Override
public String getName() {
return _name;
}
//
#Override
public int getSize() {
return _size;
}
}
//
public class Directory extends FileSystemItemContainer {
//
private String _name;
//
public Directory(String name) {
_name = name;
}
//
#Override
public void accept(FileSystemVisitor v) {
v.visitDirectory(this);
}
//
#Override
public String getName() {
return _name;
}
//
#Override
public int getSize() {
int size = 0;
for (int i = 0; i < _list.size(); i++)
{
size += _list.get(i).getSize();
}
return size;
}
}
//
public abstract class FileSystemVisitor {
//
public void visitFile(File f) { }
public void visitDirectory(Directory d) { }
//
public void vistChildren(FileSystemItemContainer c) {
for (int i = 0; i < c.getCount(); i++)
{
c.getItem(i).accept(this);
}
}
}
//
public class ListingVisitor extends FileSystemVisitor {
//
private int _indent = 0;
//
#Override
public void visitFile(File f) {
for (int i = 0; i < _indent; i++)
System.out.print(" ");
System.out.print("~");
System.out.print(f.getName());
System.out.print(":");
System.out.println(f.getSize());
}
//
#Override
public void visitDirectory(Directory d) {
for (int i = 0; i < _indent; i++)
System.out.print(" ");
System.out.print("\\");
System.out.print(d.getName());
System.out.println("\\");
//
_indent += 3;
vistChildren(d);
_indent -= 3;
}
}
//
public class XmlVisitor extends FileSystemVisitor {
//
private int _indent = 0;
//
#Override
public void visitFile(File f) {
for (int i = 0; i < _indent; i++)
System.out.print(" ");
System.out.print("<file name=\"");
System.out.print(f.getName());
System.out.print("\" size=\"");
System.out.print(f.getSize());
System.out.println("\" />");
}
//
#Override
public void visitDirectory(Directory d) {
for (int i = 0; i < _indent; i++)
System.out.print(" ");
System.out.print("<directory name=\"");
System.out.print(d.getName());
System.out.print("\" size=\"");
System.out.print(d.getSize());
System.out.println("\">");
//
_indent += 4;
vistChildren(d);
_indent -= 4;
//
for (int i = 0; i < _indent; i++)
System.out.print(" ");
System.out.println("</directory>");
}
}
//
public static void main(String[] args) {
VisitorSample s = new VisitorSample();
//
Directory root = s.new Directory("root");
root.addItem(s.new File("FileA", 163));
root.addItem(s.new File("FileB", 760));
Directory sub = s.new Directory("sub");
root.addItem(sub);
sub.addItem(s.new File("FileC", 401));
sub.addItem(s.new File("FileD", 543));
Directory subB = s.new Directory("subB");
root.addItem(subB);
subB.addItem(s.new File("FileE", 928));
subB.addItem(s.new File("FileF", 238));
//
XmlVisitor xmlVisitor = s.new XmlVisitor();
root.accept(xmlVisitor);
//
ListingVisitor listing = s.new ListingVisitor();
root.accept(listing);
}
}
The only thing that I see that is readily obvious is that by storing the interface, you make it so you have to do two operations rather than one to invoke it. I suppose that this could make sense if you are repeatedly going to perform the same action once the interface is set, but I think you could stick with the standard Visitor and accomplish the same thing.