Interface Issues

Suppose I have a MyInterface interface and 2 classes A, B that implement MyInterface.
I declared 2 objects: MyInterface a = new A() and MyInterface b = new B() .
When I try to go to the doSomething(A a){} function function, I get an error.

This is my code:

 public interface MyInterface {} public class A implements MyInterface{} public class B implements MyInterface{} public class Tester { public static void main(String[] args){ MyInterface a = new A(); MyInterface b = new B(); test(b); } public static void test(A a){ System.out.println("A"); } public static void test(B b){ System.out.println("B"); } } 

My problem is that I get a component from some interface, which can be of all kinds of classes, and I need to write a function for each class. So one way is to get the interface and check what type it is. (instance A)

I would like to know how others deal with this problem?

thanks

+4
source share
10 answers

Can you not just have a method on an interface that implements each class? Or do you have no control over the interface?

This will provide both polymorphism and avoid the need to define any external methods. I believe that this is the intention of the interface, it allows the client to consider all classes that implement it in a non-standard way.

If you cannot add to the interface, it is best for you to enter a second interface with the appropriate method. If you cannot edit the interface or classes, you need a method that takes the interface as a parameter and then checks for a specific class. However, this should be a last resort and rather undermines the use of the interface and associates this method with all implementations.

+5
source

It looks like you are after something like this:

 public static void test(MyInterface obj){ if(obj instanceof A) { A tmp = (A)obj; } else if(obj instanceof B) { B tmp = (B)obj; } else { //handle error condition } } 

But note that this is a very bad form and indicates that something is seriously wrong with your design. If you don't have control over the interface, then, as suggested by marcj, adding a second interface can be a way. Please note that you can do this while maintaining binary compatibility.

+3
source

I don’t understand what you are actually asking, but the problem is that you do not have a method that accepts a parameter of type MyInterface. I don’t know what exact syntax is in Java, but you can do something like if (b is B) {test (b as B)}, but I wouldn’t. If you want it to be generic, use the MyInterface type as the variable type, otherwise use B as the variable type. You are violating the purpose of using the interface.

+2
source

I think a visitor design template will help you here. The basic idea is for your classes (A and B) to call the appropriate method themselves, rather than trying to decide which method to call. Being a C # guy, I hope my Java works:

 public interface Visitable { void accept(Tester tester) } public interface MyInterface implements Visitable { } public class A implements MyInterface{ public void accept(Tester tester){ tester.test(this); } } public class B implements MyInterface{ public void accept(Tester tester){ tester.test(this); } } public class Tester { public static void main(String[] args){ MyInterface a = new A(); MyInterface b = new B(); a.accept(this); b.accept(this); } public void test(A a){ System.out.println("A"); } public void test(B b){ System.out.println("B"); } } 
+1
source

I'm not sure if I fully understand the problem, but it seems like one way could be to move the test () methods to child classes:

 public interface MyInterface { public void test(); } public class A implements MyInterface{ public void test() { System.out.println("A"); } } public class B implements MyInterface{ public void test() { System.out.println("B"); } } public class Tester { public static void main(String[] args){ MyInterface a = new A(); MyInterface b = new B(); b.test(); } } 

Similarly, you can use the toString () method and print the result of this. However, I cannot answer this question if your requirements make this impossible.

+1
source

Use only one public class / interface in one .java file, otherwise it will cause an error. And call the object with the name of the object. You specified only two methods in the Teater class, then the purpose of declaring classes A, B.

+1
source

I usually use an abstract class to get around this problem, for example:

public abstract class Parent {}
public class A extends Parent {...}
public class B extends Parent {...}

This allows you to pass parent objects to functions that accept A or B.

0
source

You have 3 options:

  • Visitor template; you will need to change the MyInterface type to include the visit(Visitor) method, where the Visitor class contains many methods for visiting each subclass.
  • Use if-else inside your test(MyInterface) method test(MyInterface) to check between them
  • Use the chain. That is, the ATester , BTester , etc. handlers are declared, all of which implement the ITester interface, which has the test(MyInterface) method. Then in ATester make sure the type is A before doing things. Then your main Tester class can have a chain of these testers and pass each instance of MyInterface down the chain until it reaches ITester , which can handle it. This basically turns the if-else block from 2 into separate classes.

Personally, I would go for 2 in most situations. Java lacks true object orientation. Deal with it! Coming up with various ways to use it, as a rule, it just makes complicated code.

0
source

It looks like you need to either: a) use polymorphism by placing the method on MyInterface and embedding in both B or b) some combination of the Composite and Visitor design pattern. I would start with a) and go to b) when things get cumbersome.

My extensive thoughts about the visitor:

http://tech.puredanger.com/2007/07/16/visitor/

0
source
 public interface MyInterface {} public class A implements MyInterface{} public class B implements MyInterface{} public class Tester { public static void main(String[] args){ MyInterface a = new A(); MyInterface b = new B(); test(b); // this is wrong } public static void test(A a){ System.out.println("A"); } public static void test(B b){ System.out.println("B"); } } 

You are trying to pass the object referenced by the MyInterface reference variable to the method specified by the argument with its subtype of type test(B b) . The compiler complains here because the reference variable MyInterface can refer to any object that is a subtype of MyInterface , but is not necessarily an object of B There may be runtime errors if allowed in Java. Take an example that will make the concept clearer for you. I changed your code for class B and added a method.

 public class B implements MyInterface { public void onlyBCanInvokeThis() {} } 

Now just change the test(B b) method as shown below:

 public static void test(B b){ b.onlyBCanInvokeThis(); System.out.println("B"); } 

This code will explode at runtime, if allowed by the compiler:

  MyInterface a = new A(); // since a is of type A. invoking onlyBCanInvokeThis() // inside test() method on a will throw exception. test(a); 

To prevent this, the compiler forbids such method invocation methods using superclass references.


I'm not sure what you are trying to achieve, but it looks like you want to achieve polymorphism at runtime. To do this, you need to declare a method in MyInterface and implement it in each subclass. Thus, a method call will be resolved at runtime based on the type of the object, not the reference type.

 public interface MyInterface { public void test(); } public class A implements MyInterface{ public void test() { System.out.println("A"); } } public class B implements MyInterface{ public void test() { System.out.println("B"); } } public class Tester { public static void main(String[] args){ MyInterface a = new A(); MyInterface b = new B(); b.test(); // calls B implementation of test() } } 
0
source

Source: https://habr.com/ru/post/1277338/


All Articles