I have the following scenario in Java. Let's say I have an interface, and two classes that implement this interface. As follows:
public interface myInterface {
public String printStuff();
}
public class A implements myInterface {
#Override
public String printStuff(){
return "Stuff";
}
}
public class B implements myInterface {
#Override
public String printStuff(){
return "Stuff";
}
public String printOtherStuff(){
return "Other Stuff";
}
}
How do I call the printOtherStuff method above if I define it as follows:
public static void main(String... args) {
myInterface myinterface = new B();
String str = myinterface.printOtherStuff(); // ? This does not work
}
The above calling code does not seem work. Any ideas?
myInterface myinterface = new B();
The reference type of myinterface is myInterface. That means you can only access the methods defined in the interface. You can cast it to type B in order to make the method call.
NOTE: From here on out I'll be using the proper naming conventions.
Example
MyInterface myInterface = new B();
String str = ((B)myInterface).printOtherStuff();
Just a note on this
If you need to do this, then you need to have a look at your class design. The idea of using an interface in this way is to abstract away from the details of the object's concrete implementation. If you're having to perform an explicit cast like this, then you might want to look into either changing your interface to accommodate the necessary methods, or change your class so that the method is moved into a global location (like a util file or something).
Extra Reading
You should read about reference types here, and you should have a look at casting here. My answer is a combination of the understanding of both of these things.
As an added note, take a look at the Java Naming Conventions. This is a vital piece of information for any Java developer to make understandable code.
Surely this wouldn't work because you have reference type of Interface MyInterface. At the time of method binding compiler would try to find this method in your Interface MyInterface which is not available. So you need to cast it to your class like this.
MyInterface myInterface = new B();
B newB=(B) myInterface ;//casting to class
newB.printOtherStuff();// would work fine
change myInterface
public interface myInterface {
public String printStuff();
public String printOtherStuff();
}
If you cant change myInterface, then extends myInterface
public interface myOtherInterface extends myInterface {
public String printOtherStuff();
}
Then Implements myOtherInterface
public class B implements myOtherInterface {
#Override
public String printStuff(){
return "Stuff";
}
#Override
public String printOtherStuff(){
return "Other Stuff";
}
}
public static void main(String... args) {
myOtherInterface myotherinterface = new B();
String str = myotherinterface.printOtherStuff();
}
Related
I try myself with design-patterns & -principles and have a question.
Before, sorry for the bad coding-style habit !!
I have an interface like ITest in this case:
public interface ITest
{
public void method1();
}
and then implement the methods and fields, if any, into a concrete class B like this:
public class B implements ITest
{
//This is the method from the interface
#Override
public void method1()
{
System.out.println("method1");
}
//This is another method in class B
public void method2()
{
System.out.println("method2");
}
}
Now in the application code I put it in like this:
public class Main
{
public static void main(final String args[]) throws Exception
{
//One principle says:
//programm to an interface instead to an implementation
ITest test = new B();
//method from interface
test.method1();
//this method is not accessible because not part of ITest
test.method2(); //compile-time error
}
}
You see that method2() from class B is not available because to the interface of ITest.
Now, what if I need this 'important' method?
There are several possibilities. I could abstract it in the interface or make class B abstract and extend into another class and so on, or make the reference in the main() method like:
B test = new B();
But this would violate the principle.
So, I modified the interface to:
public interface ITest
{
//A method to return the class-type B
public B hook();
public void method1();
}
And put in class B the implementation:
public class B implements ITest
{
//this returns the object reference of itself
#Override
public B hook()
{
return this;
}
//This is the method from the interface
#Override
public void method1()
{
System.out.println("method1");
}
//This is the 'important' method in class B
public void method2()
{
System.out.println("method2");
}
}
Now in my main()-method I can call both methods with a little hook or chaining mechanism without referencing a new object nor does it violate the design-principle and I don't need an extra class for extension or abstraction.
public class Main
{
public static void main(final String args[])
{
//programm to an interface instead into an implemintation
ITest test = new B();
//method from interface
test.method1();
//method2 will not be accessible from ITest so we referencing B through a method hook()
//benefits: we don't need to create extra objects nor additional classes but only referencing
test.hook().method2();
System.out.println("Are they both equal: "+test.equals(test.hook()));
}
}
Also, I can encapsulate, inherit and abstract other methods, fields etc.
This means, that I can create more complex and flexible hierarchies.
My question now:
Is this a kind of anti-pattern, bad design-principle or could we benefit from this?
Thank you for watching. :-)
Is this a kind of anti-pattern, bad design-principle or could we
benefit from this?
Yes, it is a bad pattern.
The problem stems from the fact that you have tightly coupled ITest to B. Say I want to create a new implementation of ITest - let's call it C.
public class C implements ITest
{
#Override
public B hook()
{
// How do I implement this?
}
#Override
public void method1()
{
System.out.println("method1");
}
}
There's no sane way we can implement this method. The only reasonable thing to do is to return null. Doing so would force any users of our interface to constantly perform defensive null checks.
If they're going to have to check every time before using the result of the method, they might as well just do an instanceof and cast to B. So what value are you adding? You're just making the interface less coherent and more confusing.
Adding a method returning B to interface ITest implemented by B is definitely an awful design choice, because it forces other classes implementing ITest return B, for example
public class C implements ITest {
#Override
public B hook()
{
return // What do I return here? C is not a B
}
...
}
Your first choice is better:
B test1 = new B();
C test2 = new C();
As far as I know, interfaces cannot be instantiated directly. However, whenever I compile the following code:
interface A {};
public class Test {
public static void main(String[] args){
A a = new A() {};
system.out.println(a);
it outputs the toString() of an object of class Test:
Test$16d06d69c
And when I change
A a = new A() {};
to
A a = new A();
it doesn't compile. Why is this happening? Is the interface being instantiated, or is something else happening behind the scenes?
You are defining a new anonymous inline class that implements interface A with the statement:
A a = new A() {};
And in the same statement you are constructing a new instance of your new anonymous class definition.
So no you are not instantiating an interface.
Just to expound on #bhspencer's answer in the case when A has defined methods:
An interface has no constructor and cannot be instantiated directly. it can however be implemented inline. Consider the following implementation of A:
public class B implements A {
#Override
public void printMyName() {
System.out.println("B");
}
}
And code that instantiates an instance of B:
public A a = new B();
This is equivalent syntax to an anonymous inline implementation of interface A that reads as follows:
public A a = new A() {
#Override
public void printMyName() {
System.out.println("B");
}
}
Java allows us to implement interfaces inline and instantiate them without creating an explicit separate class.
Is there a way to inline implementation of an interface without having its default constructor? To understand my question better, Lets say I have an interface MyInterface and one implementation of it called MyImplementation.
public interface MyInterface
{
void myFunction();
}
public MyImplementation implements MyInterface
{
private final String someString;
public MyImplementation(String someString)
{
this.someString = someString;
}
public void myFunction()
{
// do something.
}
}
Is there a way to inline MyImplementation? If I didn't have to pass someString to constructor of implementation I could just say -
MyInterface myInterface = new MyInterface() {
public void myFunction()
{
// do something
}
};
If your question is how to make an anonymous class that references objects that you set up in the constructor, you could "inline" an implementation by making an anonymous class and reference final local variables defined in the same method, like this:
private final String someString = ...; // That's the string that you used to init in the constructor; init it here
MyInterface myInterface = new MyInterface() { // That's the code that you wanted to have
public void myFunction()
{
System.out.println(someString); // This is allowed, because someString is final
}
};
Behind the scene, Java compiler would generate a class that looks very much like your MyImplementation class, make a constructor that looks like your MyImplementation constructor, and pass someString to it.
Anonymous classes are the "old" way to do this. The new way in Java 8, for an interface with exactly one method, is to use lambda expressions.
For instance, let's say you wanted to print someString. Old way:
MyInterface o = new MyInterface() {
#Override
public void myFunction() {
System.out.println(someString);
}
};
new way:
MyInterface o = () -> System.out.println(someString);
You don't even need to make someString final with lambdas! It's good enough that it's "effectively final," which basically means that it could have been marked final and still compiled.
Could someone explain in the following example why the interface method can be called directly when it is passed as a parameter in a class constructor? I try to search a rule in the Java language specification but can not find one.
public interface Interface {
public void foo();
}
public class Main {
public Main() {}
public Main(Interface obj) {obj.foo();}
public static int test() {return 123;}
}
Is just a polymorphic behaviour, Java expects an implementation of the method of that interface.
That means, any class which implements that method is an Interface, so you can have many many different implementations of that method.
Let's say:
public class ImplementedInterface implements Interface
{
public void foo()
{
System.out.println("Hey!, i'm implemented!!");
}
}
So when you call:
Interface aux = new ImplementedInterface();
Main m = new Main(aux);
The text "Hey!, i'm implemented!!" will be printed.
You can call foo method from Interface reference because it can hold only object of class that implements Interface, so it will provide body for foo method.
Now thanks to late binding Java will use code of object class when needed.
I think that you are confused, you think cuase it's Interface type it's an interface
public Main(Interface obj) {
obj.foo();
}
obj is an object from a concrete implementation of Interface.
You may want to see some common design pattern that take this approach such as Strategy Pattern
For example :
public interface Searcher {
void search(String text, List<String> words);
}
public class BinarySearcher implements Searcher{
#Override
public void search(String text , List<String> words){
//code here
}
}
public class LinearSearcher implements Searcher{
#Override
public void search(String text ,List<String> words ){
// code here
}
}
public class WordContext {
private Searcher searcher;
private List<String> words;
public void makeSearch(String text){
searcher.search(); // you only know at runtime what subtype will be searcher
}
// here you inject by contract
public void setSearcher(Searcher searcher){
this.searcher= searcher;
}
// here you inject by contract
public void setWords(List<String> words){
this.words = words;
}
}
That's the main advantage you guide by abstract contract instead of concrete implementation.
In this example you can change the searcher injecting it, can be a linearSearcher or a binarySearcher, that's the polymorphic magic!
Here is where Programming to an interface, not an implementation comes into play. Your method is expecting an object of the class that that implements the interface
I would explain it with an example.
Let us say I have
LinkedList<String> ll = new LinkedList<String>();
and I have
ArrayList<String> al = new ArrayList<String>();
Now I have a method -
public void deleteFirst(List aList) {
System.out.println(aList.remove(0));
}
Now you can pass both ll and al to the deleteFirst method. Which means your method is passed an object of the class that that implements the interface.
In the example ArrayList and LinkedList both implement the List interface and therefore can be passed to the method. Ultimately what your method is getting is an object of the class that implements the List interface.
Suppose that I have interface MyInterface and 2 classes A, B which implement MyInterface.
I declared 2 objects: MyInterface a = new A() , and MyInterface b = new B().
When I try to pass to a function - function doSomething(A a){} I am getting 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 am getting from some component interface which can be all sorts of classes and I need to write function for each class.
So one way is to get interface and to check which type is it. (instance of A)
I would like to know how others deal with this problem??
Thx
Can you not just have a method on the interface which each class implements? Or do you not have control of the interface?
This would provide both polymorphism and avoid the need to define any external methods. I believe this is the intention of an interface, it allows a client to treat all classes implementing it in a non type specific manner.
If you cannot add to the interface then you would be best introducing a second interface with the appropriate method. If you cannot edit either the interface or the classes then you need a method which has the interface as a parameter and then check for the concrete class. However this should be a last resort and rather subverts the use of the interface and ties the method to all the implementations.
It sounds 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 please note this is very bad form and indicates something has gone seriously wrong in your design. If you don't have control of the interface then, as suggested by marcj, adding a second interface might be the way to go. Note you can do this whilst preserving binary compatibility.
I'm unclear on what you're actually asking, but the problem is that you don't have a method that takes a parameter of type MyInterface. I don't know what the exact syntax is in Java, but you could do something like if (b is B) { test(b as B) } but I wouldn't. If you need it to be generic, then use the MyInterface type as the variable type, otherwise use B as the variable type. You're defeating the purpose of using the interface.
I'm not sure if I fully understand the issue, but it seems like one way might be to move the test() methods into the 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();
}
}
You could similarly use a toString() method and print the result of that. I can't quite tell from the question, though, if your requirements make this impossible.
I think visitor design pattern will help you out here. The basic idea is to have your classes (A and B) call the appropriate method themselves instead of you 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");
}
}
Use only one public class/interface in one .java file, otherwise it'll throw error. And call the object with the object name.. You declared two methos in Teater class only, then what the purpose of declaring class A,B.
I usually use an abstract class to get around this problem, like so:
public abstract class Parent {}
public class A extends Parent {...}
public class B extends Parent {...}
That allows you to pass Parent objects to functions that take A or B.
You have 3 options:
Visitor pattern; you'll need to be able to change the MyInterface type to include a method visit(Visitor) where the Visitor class contains lots of methods for visiting each subclass.
Use if-else inside your method test(MyInterface) to check between them
Use chaining. That is, declare handlers ATester, BTester etc, all of which implement the interface ITester which has the method test(MyInterface). Then in the ATester, check that the type is equal to A before doing stuff. Then your main Tester class can have a chain of these testers and pass each MyInterface instance down the chain, until it reaches an ITester which can handle it. This is basically turning 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 around it usually just makes for difficult-to-follow code.
Sounds like you need either a) to leverage polymorphism by putting method on MyInterface and implementing in A and B or b) some combination of Composite and Visitor design pattern. I'd start with a) and head towards b) when things get unwieldy.
My extensive thoughts on Visitor:
http://tech.puredanger.com/2007/07/16/visitor/
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 an object referenced by MyInterface reference variable to a method defined with an argument with its sub type like test(B b). Compiler complains here because the MyInterface reference variable can reference any object which is a sub type of MyInterface, but not necessarily an object of B.There can be runtime errors if this is allowed in Java. Take an example which will make the concept clearer for you. I have modified your code for class B and added a method.
public class B implements MyInterface {
public void onlyBCanInvokeThis() {}
}
Now just alter the test(B b) method like below :
public static void test(B b){
b.onlyBCanInvokeThis();
System.out.println("B");
}
This code will blow up at runtime if allowed by 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, compiler disallows such method invocation techniques with super class reference.
I'm not sure what are you trying to achieve but it seems like you want to achieve runtime polymorphism. To achieve that you need to declare a method in your MyInterface and implement it in each of the subclass. This way the call to the method will be resolved at run time based on the object type and not on 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's implementation of test()
}
}