Yesterday I asked this question, and the solution posted by #JB Nizet worked perfectly. However, that answer, as well as a few other answers/comments got me thinking in a different direction altogether.
Essentially, I have the following classes:
Load
HttpLoad extends Load
Target
HttpTarget extends Target
Controller
The Controller's job is to Target::fire() a Load, and doesn't care which Target is firing which Load:
// Inside Controller.java
Target target = getTarget();
Load load = getLoad();
target.fire(load);
However, I might some day write a FtpLoad extends Load, and I don't want to be able to fire a FtpLoad at an HttpTarget. So the essence of the above-referenced question was how do I do this, to which, the answer was generics.
However, as the answerer pointed out, this solution is a violation of the Liksov Substitution Principle. Other answerer/commenters seemed to indicate that what I was doing wasn't necessarily good OOP practices.
So now I'm asking: how do I expose an API so that the Controller can be Load- and Target-agnostic, but still enforce that the proper Load subclass is fired on the proper Target type, all without violating Liskov Substitution?
And, if this is impossible to do (without violating Liskov), then what is the normal approach to a problem like this? Thanks in advance!
If HttpTarget.fire allows any Load as parameter, it is its job to check if it can fire this Load. So either the Controller calls fire blindly, and fire checks if the given target can fire that kind of Load (with instanceof), or you include a function canFire in every target that implements this check and is called by the Controller.
The typing problem here is that HttpTarget is not a Liskov subtype of Target, because semantically it is attempting to strengthen the preconditions of Target#fire(Load) to require the Load be HttpLoad.
This can be trivially repaired by declaring Target#fire(Load) throws IncompatibleLoadException and having a default implementation that always throws, forcing Controller to deal with the fact that a mismatched Load can be passed in.
The easy way is to do some checking in your code to make sure the classes match up. You can use the instanceof keyword to check if it's the correct class.
Best is to implement abstract class or an interface and use instanceof as mentioned before.
With an abstract class:
public abstract class TargetLoad {
public abstract void fire(TargetLoad i);
}
public class Load extends TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Target) return;
// do fire stuff
}
}
public class Target extends TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Load) return;
// do fire stuff
}
}
with an interface:
public interface TargetLoad {
public void fire(TargetLoad i);
}
public class Load implements TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Target) return;
// do fire stuff
}
}
public class Target implements TargetLoad {
#Override
public void fire(TargetLoad i) {
if (i instanceof Load) return;
// do fire stuff
}
}
In your Controller you refer to your objects as TargetLoad
TargetLoad target = getTarget();
TargetLoad load = getLoad();
target.fire(load);
load.fire(target);
load.fire(load); //this will do nothing
target.fire(target); //this will do nothing
I strongly disagree with the slew of answers recommending to use instanceof. Well-written OOP code very rarely needs to use instanceof, and using instanceof will generally make your code awkward and difficult to maintain. As a general rule, avoid instanceof if at all possible.
The previous question you referred to provided a solution using generics. I'm not sure you left the generics code out of your question here; go back to your generic code. Now, add the following method to your driver.
private <L extends Load> void runSuite(TestSuite<L> suite) {
Target<L> target = testSuite.getTarget();
L load = testSuite.getLoad();
target.fire(load);
}
Related
I am currently working on a piece of code, in which behavioral decisions are made based on whether the request object is of a certain sub-type, like so:
class Request{
public void doThing(){
System.out.println("doing Thing...");
}
}
class SpecialRequest extends Request{
...
}
void method(Request request){
if(request instanceof SpecialRequest){
System.out.println("is special...");
}
request.doThing();
}
SpecialRequest in this case has nothing else implemented, that would distinguish it from a normal Request. My question now is, if there are any advantages or disadvantages from using this style instead:
class Request{
...
public boolean isSpecial(){
return special;
}
public void doThing(){
System.out.println("doing Thing...");
}
}
void method(Request request){
if(request.isSpecial()){
System.out.println("is special...");
}
request.doThing();
}
I understand how the second Method could get very convoluted the more decisions I want to make. But I am also interested in how these two approaches compare performance wise.
Thanks in advance.
EDIT: First of all thanks for the quick response. I should have probably mentioned, that my Request and my SpecialRequest are supposed to merely carrying data, and not contain any logic. That's just how the whole software is designed. My method just consumed the request and is supposed to behave differently based on whether the request is special or not. "instanceof" just seems like dirty code to me, but the boolean also doesn't seem quite right. Any advice is still welcome.
The clear advantage of using a method is that it's not closely tied to a particular type. You could add a new class VerySpecialRequest which also provides this behaviour, and you wouldn't necessarily need to extend SpecialRequest in order to do that.
However, the more pressing issue here is that you have explicit conditional branching at all. The object should be responsible for determining whether there's any additional behaviour required, and then the nasty conditional logic goes away altogether:
class Request{
public void doThing(){
System.out.println("doing Thing...");
}
}
class SpecialRequest extends Request{
#Override
public void doThing(){
super.doThing();
System.out.println("is special...");
}
}
You might also consider using the visitor pattern (https://en.wikipedia.org/wiki/Visitor_pattern), as it ensures type-safety and does not need the instanceof-check. Furthermore it is more obvious where you have to extend/ modify your code, when you create a new type of request (e.g. "VerySpecialRequest").
All you have to do is to create an interface with visit-methods for every type you want to execute special code, like this:
public interface RequestProcessor {
void visit(Request request);
void visit(SpecialRequest specialRequest);
}
The request classes need accept-methods that do nothing but calling the visitor with itself:
public class Request {
...
void accept(RequestProcessor requestProcessor) {
requestProcessor.visit(this);
}
}
Same for SpecialRequest:
public class SpecialRequest extends Request {
...
#Override
void accept(RequestProcessor requestProcessor) {
requestProcessor.visit(this);
}
}
Then you can simply implement your logic in a class that implements the interface (here as an anonymous class):
RequestProcessor requestProcessor = new RequestProcessor() {
#Override
public void visit(Request request) {
System.out.println("I'm a normal request");
}
#Override
public void visit(SpecialRequest specialRequest) {
System.out.println("I'm a special request");
}
};
Request request = new Request();
request.accept(requestProcessor);
SpecialRequest specialRequest = new SpecialRequest();
specialRequest.accept(requestProcessor);
As you can see there are no more instance-of checks. Another advantage of this is that you can "process requests" even if they are no direct subclass of 'Request' - all you have to do is to extract the accept-method in its own interface. Hope this helps.
1.- insteadof, is a type comparison operator because it compares the instance with type. It returns either true or false. If you apply the instanceof operator with any variable that has null value, it returns false.
2.- isSpecial(), is a method of your own. You can do what ever you want in that piece of code, so the comparisson in that case is up to you.
3.- You have to be aware that when you use instanceof, the comparison also do a class cast of the variable in mention, so if that can't be done, you should get a compile time error. see this : compile time error with instanceof
4.- if you use this operator to much, you should check it, because that's a signal of some bad code. For more details see this: use of instaceof
Say, I have a package Pack containing classes A and B. A is self-contained and no one (even in the Pack) should see A's insides, so most of the fields and methods are private.
Now I want to extend A to change one of its private methods keeping the rest - let it be class AMod. Doing it requires most of A's fields and the method to override to be protected, but protected gives access to the package.
So how do I create AMod inside Pack so that AMod has an access to A's fields and methods while no one else does? Make a nested/separate package?
UPD:
UPD2:
UPD3:
As Jacob G. suggested, my code needed redesigning, and I managed to remove the derived class from the architecture. Thanks for help!
The one answer I find missing: don't be so focused on using inheritance in order to avoid code duplication.
If you only need a subtle variation of behavior of A then you should first consider to "wrap" around A (for example via decorator) instead of extending A - the good old FCoI!
If that isn't possible: have a very close look at the common behavior of A and Amod and extract those parts in a common base class.
Finally: don't get too energetic about java access modifiers in the first place. In the end, they help you to communicate a certain thought or idea. "Evil-willing" people will always find a way to work around your intentions. What I am saying is: if you are concerned that your team members use your class in the wrong way ... that is a social problem; and you will never be able to solve that on the technical layer. You have to solve it on the social layer, too (by educating people to ensure that they understand what to do; instead of hoping that private here or protected there will prevent them from doing the wrong thing).
In other words: establish a simple policy such as "only what is marked public is meant to be public; anything else is not" might be able to table such discussions for all times. Versus spending hours and hours to find a perfect private-protected solution within source code.
Thanks for posting code.
My advice would be to first move B#stepBMod into A.java. Then, you can pass a boolean parameter to A#build; with this, you can rewrite A#build:
public Result build(boolean mod) {
stepA();
if (mod) {
stepBMod();
} else {
stepB();
}
stepC();
return result;
}
Now, B.java isn't needed anymore.
Your question is two parts. 1)Accessing fields and 2)Accessing methods.
Case1), you should make class A's fields protected. This means no one can access it by name, except derived classes.
Case2), you cannot access a protected method by name, unless in a derived class. But still you can access a protected method by name using an object of A. In order to prevent other classes making objects, your A class should be abstract.
Here is an example
public abstract class A{
protected int n;
protected void display(){
System.out.println(n);
}
}
public class B extends A{
public void demo(){
B object = new B();
object.display();
}
public void modify(){
n = 0;
}
}
Update
class A
{
public A(Args args){...}
public Result build() {
stepA();
stepB();
stepC();
return result;
}
protected void stepA() {...}
private void stepB() {...}
protected void stepC() {...}
protected T field;
}
class AMod extends A
{
public AMod(Args args){
super(args);
...
}
public Result build() {
stepA();
stepBMod();
stepC();
return result;
}
private void stepBMod() {...}
}
I use Hibernate for persistence.
Suppose I have an entity which contains information about the document and the necessary information for producing it (either printing or sending by email). Just like this:
The problem here is that DocumentInformation holds reference to abstract class DocumentProductionConfiguration not to the subclasses DocumentPrintConfiguration or DocumentEmailConfiguration.
So when I actually need to get appropriate configuration I have two choices: either use instanceof + casting or use visitor pattern to trick Java so that it would actually understand in the runtime which configuration it is dealing with.
Using casting:
public class XmlBuilder{
public XMLMessage buildXmlMessage(DocumentInformation documentInformation){
if(documentInformation.getDocumentProductionConfiguration() instanceOf DocumentPrintConfiguration){
DocumentPrintConfiguration printConfig = (DocumentPrintConfiguration) documentInformation.getDocumentProductionConfiguration();
XMLMessageConfig xmlConfig = handlePrintConfig(printConfig);
}
}
public XMLMessageConfig handlePrintConfig(DocumentPrintConfiguration printConfig){
....build that XMLMessageConfig....
}
}
Using visitor pattern:
I need to add a new interface for XmlBuilder to implement
public interface XmlBuilderVisitor<T> {
T handlePrintConfig(DocumentPrintConfiguration printConfig);
}
public class XmlBuilder implements XmlBuilderVisitor<XMLMessageConfig> {
#Override
public XMLMessageConfig handlePrintConfig(DocumentPrintConfiguration printConfig){
....build that XMLMessageConfig....
}
public XMLMessage buildXmlMessage(DocumentInformation documentInformation){
XMLMessageConfig xmlMessageConfig = documentInformation.getDocumentProductionConfiguration().buildConfiguration(this);
}
}
public abstract class DocumentProductionConfiguration{
public abstract <T> T buildConfiguration(XmlBuilderVisitor<T> visitor);
}
public class DocumentPrintConfiguration extends DocumentProductionConfiguration{
public <T> T buildConfiguration(XmlBuilderVisitor<T> visitor){
return visitor.handlePrintConfig(this);
}
}
Both of these solutions are kinda meh... The first one because it violates open-closed principle (I will need to always maintain these ifs...).
The second one in this sense is better: once you add new configuration, compiler will guide you through the process: first, you will need to implement appropriate method in the configuration itself, then in all the visitor classes. On the other hand, it is pretty awkward that I am basically passing service to the entity...
So I feel like I am treating symptoms rather than the problem. Maybe the design itself needs some changes? But I am not sure how it could be improved...
I would reccomend pushing the "handle" functionality into the DocumentProductionConfiguration and subclasses. So that the DocumentPrintConfiguration would contain a handle function that builds and returns a XMLMessageConfig. Then your XmlBuilder becomes:
public class XmlBuilder{
public XMLMessage buildXmlMessage(DocumentInformation documentInformation){
XMLMessageConfig xmlConfig = documentInformation.getDocumentProductionConfiguration().handle();
}
}
We are trying to implement the MVP pattern. Because it requires quite a lot of code just to have a functioning view, we try to use inheritance as much as possible. As I am pretty new to Java, I don't know exactly if I'm doing it right:
So, I started with a very simple Interface which all the views will implement (and the `getName`` method will be used for breadcrumb Feature):
public interface IView {
public String getName();
}
On top of that, I built a BaseView which will be used for most views:
public interface IBaseView extends IView {
public void addListener(IBaseViewListener l);
interface IBaseViewListener {
void viewEntered(Long id);
}
}
And the implementation
public class BaseView extends CustomComponent implements View, IBaseView{
private String name = "";
private List<IBaseViewListener> listeners;
public BaseView(String name) {
this.name = name;
listeners = new ArrayList<IBaseViewListener>();
buildLayout();
}
#Override
public void addListener(IBaseViewListener l) {
listeners.add(l);
}
protected void buildLayout() {
this.setId("base_view");
// initialize layout....
}
#Override
public void enter(ViewChangeEvent event) {
for (IBaseViewListener l : listeners) {
l.viewEntered(id);
}
}
#Override
public String getName() {
return name;
}
}
And last we have a ScaffoldingView which will be used for some views (mainly for mocking):
public interface IScaffoldingView extends IBaseView{
public void showTable(AbstractComponent t);
interface IScaffoldingViewListener extends IBaseViewListener {
void itemSelected(DataBaseObject selectedObject);
}
}
And the implementation:
public class ScaffoldingView extends BaseView implements IScaffoldingView{
private AbstractComponent table = null;
public ScaffoldingView(String name) {
super(name);
}
#Override
protected void buildLayout() {
// here is a lot more code...
}
public void showTable(AbstractComponent t) {
// here is a lot of code...
}
}
First of all:
- Does that approach make any sense? especially the access modifiers. I'm totally weak when it Comes to polymorphism :(
I am very unsure about the handling of the EventListeners. For example: In the constructor of the BaseView, I am implementing the addListener function.
Now, in the ScaffoldingView's, there will be a specialized IScaffoldingViewListener. Will the super class (BaseView) addListener() method be able to handle These IScaffoldingViewListeners?
edit: Sorry, I forgot to mention that View and CustomComponent are some classes of a 3rd Party Framework (Vaadin) which we use and which offer the enter Event in which we call the eventListeners (Presenter).
First, declaring an interface inside another interface is not quite clean, obscures the code quite a bit.
Second, about BaseView which extends CustomComponent, and implements IView and IBaseView, first a small detail, if it implements IBaseView, you do not need to implement IView, as IBaseView already extends IView, but the bigger issue i see is:
If you have a somewhere in some class, a method with an IBaseView as a parameter, but inside that function you expect to be able to use the overrided methods from CustomComponent, you won't be able to, you'll only have the methods declared on IBaseView.
If you wanted to use the CustomComponent methods, you'd had to do a cast inside that method, but that is not clean and a source of bugs, because if in the future, you add more classes that implement IBaseView but do not extend CustomComponent, that function will throw exceptions complaining about casting.
Also, about the ScaffoldingView, if you are going to use it only for mocking purposes in tests and you are extending the IBaseView behaviour, with more methods, if you test a method that has an IBaseView as parameter, you have the same exact situation as before, the method you are testing will not be aware of the IScaffoldingView declared methods, and then it won't use them, and your tests can't be trusted.
P.D.: if you are interested in learning about abstractions and inheritance design, i'd recomend you to check S.O.L.I.D. principles, there's a lot of literature in the web about those.
Edit: Response to your comment
First you need to ask yourself without thinking about internal details or implementations or testing or anything else, what are the behaviour my Views have? are they all behaving the same way? do i have different types of views or not really? Once you answer these questions and got an idea of what is going on, you'll have what it will need to design the interface hierarchy, and thats what is going to be exposed to the rest of the system.
You can (optionally) have abstract classes that derive from those interfaces, where you can provide some initialization, defaults, but, do not go further in offering more functionality than the interface offers, you can have some extra methods, but only for internal use.
And then you can derive the actual implementation of the views from the interface or the intermediate abstract classes if you have defined any.
Just think of this as a black box, in which the only thing you can see are the input and output interfaces, everything else that is going inside that box, the rest of the system doesn't and shouldn't need to know about.
Can't really give you specific solution because i'm not aware of the needs of your application.
Sorry for the poor title, can't think of a succinct way of putting this..
I'm thinking of having a list of objects that will all be of a specific interface. Each of these objects may then implement further interfaces, but there is no guarantee which object will implement which. However, in a single loop, I wish to be able to call the methods of whatever their further sub-type may be.
Ie, 3 interfaces:
public interface IAnimal { ... }
public interface IEggLayer { public Egg layEgg(); }
public interface IMammal { public void sweat(); }
this would then be stored as
private List<IAnimal> animals= new ArrayList<IAnimal>();
so, instances added to the list could possibly also be of type IEggLayer or IMammal, which have completely unrelated methods.
My initial instinct would be to then do
for(IAnimal animal : animals) {
if(animal instanceof IEggLayer) {
egg = ((IEggLayer)animal).layEgg();
}
if(animal instance of IMammal) {
((IMammal)animal).sweat();
}
}
But I have always been told that type checking is a sign that the code should really be refactored.
Since it could be possible for a single object to do both [platypus, for example], meaning that a single doFunction() would not be suitable here, is it possible to avoid using type checking in this case, or is this an instance where type checking is classed as acceptable?
Is there possibly a design pattern catered to this?
I apologise for the contrived example as well...
[Ignore any syntax errors, please - it's only intended to be Java-like pseudocode]
I've added lvalue to the EggLayer use, to show that sometimes the return type is important
Clearly your IAnimal interface (or some extension thereof) needs a callAllMethods method that each implementer of the interface can code to polymorphically perform this task -- seems the only OO-sound approach!
But I have always been told that type checking is a sign that the code should really be refactored.
It is a sign that either class hierarchy or the code that uses it may need to be refactored or restructured. But often there will be no refactoring / restructuring that avoids the problem.
In this case, where you have methods that apply only to specific subtypes, the most promising refactor would be to have separate lists for the animals that are egg layers and the animals that sweat.
But if you cannot do that, you will need to do some type checking. Even the isEggLayer() / isMammal() involves a type check; e.g.
if (x.isEggLayer()) {
((IEggLayer) x).layEgg(); // type cast is required.
}
I suppose that you could hide the type check via an asEggLayer() method; e.g.
public IEggLayer asEggLayer() {
return ((IEggLayer) this);
}
or
// Not recommended ...
public IEggLayer asEggLayer() {
return (this instanceof IEggLayer) ? ((IEggLayer) this) : null;
}
But there is always a typecheck happening, and the possibility that it will fail. Furthermore, all of these attempts to hide the type checking entail adding "knowledge" of the subtypes to the supertype interface, which means that it needs to be changed as new subtypes are added.
in C#, you should be able to do this transparently.
foreach(IEggLayer egglayer in animals) {
egglayer.layEgg();
}
foreach(IMammal mammal in animals) {
mammal.sweat();
}
I think the way to think about this question is: What is the loop doing? The loop has a purpose and is trying to do something with those objects. That something can have a method on the IAnimal interface, and the implementations can sweat or lay eggs as needed.
In terms of your issue with the return value, you will be returning null, nothing you can do about that if you share the methods. It is not worth casting within a loop to avoid an extra return null; to satisfy the compiler. You can, however, make it more explicit using generics:
public interface IAnimal<R> {
public R generalMethod();
}
public interface IEggLayer extends IAnimal<Egg> {
public Egg generalMethod(); //not necessary, but the point is it works.
}
public interface IMammal extends IAnimal<Void> {
public Void generalMethod();
}
From your comment where you care about the return type, you can get the return type and dispatch it to a factory method which examines the type and returns something generic that is sublcassed to the specific type and act on that.
Why not have methods added to isAnimal:
public interface IAnimal {
bool isEggLayer();
bool isMammal();
}
Then you can loop through and just query this boolean each time.
Update:
If this was drawing an animal, then having a class that is completely enclosed is reasonable, you just call drawVehicle and it draws a corvette, cessna, motorcycle, whatever.
But, this seems to have a non-OOP architecture, so if the architecture of the application can't change then, since my original answer isn't well received, then it would seem that AOP would be the best choice.
If you put an annotation on each class, you can have
#IsEggLayer
#IsMammal
public class Platypus() implements EggLayer, Mammal {
...
}
This would then enable you to create aspects that pull out all the egglayers and do whatever operations need to be done.
You can also inject into the animal interfaces any additional classes to get this idea to work.
I will need to think about where to go from here, but I have a feeling this may be the best solution, if a redesign can't be done.
There are many ways of going about this. Exaclty which is most appropriate depends upon your context. I am going to suggest introducing an additional layer of indirection. This solves most problems. I prefer designs which avoid multiple inheritance of interface (if I were president of a language, I would forbid it).
I don't think layEggsOrSweatOrDoBothIfYoureWeirdOrNoneIfYouCant() is a great method to polute Animal with. So instead of adding each Animal directly to animals, wrap each in an individual wrapper. I say "wrapper" as a generic name - the random operation we are trying to perform doesn't make any sense.
private final List<AnimalWrapper> animals =
new ArrayList<AnimalWrapper>();
public void doStuff() {
for (AnimalWrapper animal : animals) {
animal.doStuff();
}
}
Then we need some way of adding the wrappers. Something like:
public void addPlatypus(final Platypus platypus) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
platypus.sweat();
platypus.layEgg();
}});
}
If you try to write these wrappers without enough context you get into trouble. These require that the correct one is selected at call site. It could be done by overloading, but that has dangers.
/*** Poor context -> trouble ***/
public void addNormalMamal(final Mamal mamal) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
mamal.sweat();
}});
}
public void addNormalEggLayer(final EggLayer eggLayer) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
eggLayer.layEgg();
}});
}
public <T extends Mamal & EggLayer> void addMamalEggLayer(final T animal) {
animals.add(new AnimalWrapper() { public void doYourStuff() {
animal.sweat();
animal.layEgg();
}});
}