There is a interface named SceneShape(see Figure 1):
public interface SceneShape
{
void setSelected(boolean b);
boolean isSelected();
void draw(Graphics2D g2);
void drawSelection(Graphics2D g2);
void translate(int dx, int dy);
boolean contains(Point2D aPoint);
}
Figure 2. A CRC Card
public interface SceneShape
{
void setSelected(boolean b);
boolean isSelected();
void draw(Graphics2D g2);
void drawSelection(Graphics2D g2);
void translate(int dx, int dy);
boolean contains(Point2D aPoint);
}
Figure 1. The Scene Editor
Then define classes CarShape and HouseShape that implement this interface type. However, there is some commonality between these classes. Every shape needs to keep a selection flag.[1] The naive approach would be to supply the selection flag separately in each class:
public class HouseShape implements SceneShape
{
... ...
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected; }
private boolean selected;
}
public class CarShape implements SceneShape
{
... ...
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected; }
private boolean selected;
}
If we create a class that expresses this commonality and we call this class SelectableShape.
public class SelectableShape implements SceneShape
{
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected };
private boolean selected;
}
public class HouseShape implements SceneShape
{
... ...
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected; }
private boolean selected;
}
public class CarShape implements SceneShape
{
... ...
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected; }
private boolean selected;
}
If we create a class that expresses this commonality and we call this class SelectableShape.
public class SelectableShape implements SceneShape
{
public void setSelected(boolean b) { selected = b; }
public boolean isSelected() { return selected };
private boolean selected;
}
As we can see, there is a problem with the SelectableShape class. It doesn't define all of the methods of the SceneShape interface type. There are four methods left in this class. So we can say that these methods are undefined or abstract in the SelectableShape class. It is the job of further subclasses to define them.[2] For that reason, the SelectableShape class must be tagged as abstract:
public abstract class SelectableShape implements SceneShape { ... ... }
Abstract classes are convenient placeholders for factoring out common behavior. They behave exactly same as any other classes. I am often scared about abstract classes, equating "abstract" with "hard to understand", and then believing that any class that is hard to understand should therefore be abstract. After using the abstract class many times, I find that abstract class is simply a class that cannot be instantiated, generally because its has unimplemented methods.
References:
[1] San Jose State University, Suneuy Kim,
http://cs.sjsu.edu/~kim/cs151/index.html
[2] San Jose State University, Cay Horstmann,
http://www.sjsu.edu/people/cay.horstmann/
References:
[1] San Jose State University, Suneuy Kim,
http://cs.sjsu.edu/~kim/cs151/index.html
[2] San Jose State University, Cay Horstmann,
http://www.sjsu.edu/people/cay.horstmann/


No comments:
Post a Comment