Is using Java instanceOf compatible with the "program for interface" principle?

As you know, the design principle “program for the interface” widely prefers supertypes instead of specific types or implementations.

Is this consistent with the principle of using instanceof in a Java program to get a specific type from a supertype?

In my application, the repository is an abstract supertype class with several private variables and public getters and setters.

ConcreteStorehouseA inherits from stock and has many specific methods and variables. ConcreteStorehouseB is similar but different.

My application receives a warehouse. However, storage is not a useful type to work with. Since only specific useful methods are contained in specific types, I use instanceof as follows:

if (storehouse instanceof ConcreteStorehouseA) { ConcreteStorehouseA concreteStorehouseA = (ConcreteStorehouseA) storehouse; // perform operations on the concrete type useful methods and variables 

Uses instanceof principle compatible?

Edit:

In essence, the application is a cube simulator for a desktop RPG, Shadowrun. Specific types are different types of tests - a success test, an opposed test, an extended test that has very different factors and parameters for successful work. A supertype essentially contains a pool of cubes!

+8
java instanceof design-principles
source share
7 answers

As a rule, this principle of “program for interfaces”, which you spoke about, can be translated into: import only the type of interface, has no dependence on compilation time in subclasses.

Therefore, the answer to your question will definitely be negative. You do not program on interfaces because you use specific types.

+10
source share

You said it yourself:

My application receives a warehouse. However, storage is not a useful type to work with. Since the only really useful methods are contained in specific types

In other words, your Storehouse abstraction doesn't buy you anything ... why do you have this?

Could you create abstract methods in the Storehouse , implemented in each concrete class, which will then allow you to process specific types in the same way in your client code? This is the goal of abstraction.

+8
source share

Not really. If your method has a completely different behavior depending on the type it receives, polymorphism does not buy anything. You should consider two separate overloaded methods: one takes ConcreteStorehouseA as an argument, and the other takes ConcreteStorehouseB .

+2
source share

This is not always a sin. Suppose you implement a specification that says that if x is A, do it, otherwise if x is Y. It is better for your code to look like a specification. Artificially cut it into small pieces and place it in difference sources, it is not only ambitious, but also difficult, unsafe, difficult to understand and difficult to maintain.

Programming problems are multidimensional. Programming languages ​​are one-dimensional, at least for now. This is the art of how to closely relate related issues. Do not buy in the dogma that problems should be decomposed according to classes, then the problem can in most cases refer to one class and should be inside this class.

In the last century, this is a great taboo in the field of software development, according to experts who knew how to write the best software products, that is, code changes should be avoided at all costs. If you are going to change some source code that you wrote earlier, the universe can crash into peanuts at any time. Thus, you better design the ideal architecture from the very beginning, and then any change in the requirement can be made by adding a new / clean class without touching the existing code base.

That is, let me be very precise in the wording here, complete stupidity, even then.

Today we have much better tools, and changing the code is not only safe, but even encouraged. The best way to make sure that code changes have become easy due to unforeseen reasons is to keep the code as simple as possible today. Write the code so that you can understand even with a comma.

+2
source share

It's hard to be sure without understanding what operations you are performing, but a more elegant design would be for StorageHouse to define method signatures for different "operations". Then, instead of if (instanceof) checks, you just perform the operations, and specific stores will perform those operations.

 public abstract class Storehouse //add these definitions; public void operation1(); public void operation2(); public class ConcreteStorehouseA public void operation1() { //do operation } public void operation2() { //do operation } public class ConcreteStorehouseB public void operation1() { //do operation } public void operation2() { //do operation } 

In the call code, not:

 if (storehouse instanceof ConcreteStorehouseA) { ConcreteStorehouseA concreteStorehouseA = (ConcreteStorehouseA) storehouse; // perform operations } else if (storehouse instanceof ConcreteStorehouseB) { ConcreteStorehouseB concreteStorehouseB = (ConcreteStorehouseB) storehouse; // perform operations } 

Then you can use polymorphism to perform operations without worrying about which implementation is being performed.

 storehouse.operation1(); storehouse.operation2(); 

where concrete StorehouseA and ConcreteStorehouseB have defined implementations for these operations.

+1
source share

It seems that the Storehouse abstraction is not actually an abstraction at all in this case. As a type in itself, this gives you nothing.

One thing that can help is to try not to think of your implementations as types at all. A "type" is an abstraction that a class implements. (Basically, separate the terms “class” and “type” in your thinking.) So the type you're working with is the Storehouse . ConcreteStorehouseA is the Storehouse as well as ConcreteStorehouseB . So the question is, what is a Storehouse ? This is the type that defines each of them.

In this particular case, it sounds like the different Storehouse implementations are so different (at least in their current implementation) that they do not actually share a significant abstraction. The abstract "type" in this case simply provides some common functions through inheritance, rather than abstracting the type.

In other words, Storehouse implementations here seem to be a classic example of Liskov motivational poster here: http://www.lostechies.com/blogs/derickbailey/archive/2009/02/11/solid-development-principles-in-motivational-pictures .aspx

+1
source share

As various people note, this is not interface programming. The abstraction of the interface seems to be too weak for your requirements.

There are various ways to deal with this: among them:

  • If the interface is under your control, you can expand it. Think about whether it’s worth it, it may be too high a price to pay, especially if the next marker point is held.
  • If you use only one type of specific warehouse, you can simply use it directly.
  • If you need to support different types of warehouses, a good alternative is to define your own interface, which provides exactly the abstraction that you need, and write a thin shell for each type of a particular class (adapter template).
0
source share

All Articles