I have two interfaces:
interface A {
void foo();
}
interface B {
void bar();
}
I am able to create anonymous instances of classes implementing either of these interfaces like so:
new A() {
void foo() {}
}
or:
new B() {
void bar() {}
}
I want to create an anonymous class that implements both interfaces. Something like (the fictitious):
new A implements B {
void foo() {}
void bar() {}
}
This obviously gives a compile error: "B cannot be resolved to a type".
The workaround is quite simple:
class Aggregate implements A, B {
void foo() {}
void bar() {}
}
I then use Aggregate where ever I would have used the anonymous class.
I was wondering if it is even legal for an anonymous class to implement two interfaces.
"An anonymous inner class can extend one subclass or implement one
interface. Unlike non-anonymous classes (inner or otherwise), an anonymous
inner class cannot do both. In other words, it cannot both extend a class and
implement an interface, nor can it implement more than one interface. " (http://scjp.wikidot.com/nested-classes)
If you are determined to do this, you could declare a third interface, C:
public interface C extends A, B {
}
In this way, you can declare a single anonymous inner class, which is an implementation of C.
A complete example might look like:
public class MyClass {
public interface A {
void foo();
}
public interface B {
void bar();
}
public interface C extends A, B {
void baz();
}
public void doIt(C c) {
c.foo();
c.bar();
c.baz();
}
public static void main(String[] args) {
MyClass mc = new MyClass();
mc.doIt(new C() {
#Override
public void foo() {
System.out.println("foo()");
}
#Override
public void bar() {
System.out.println("bar()");
}
#Override
public void baz() {
System.out.println("baz()");
}
});
}
}
The output of this example is:
foo()
bar()
baz()
For save some keystrokes (for example if the interfaces have a lot of methods) you can do this:
abstract class Aggregate implements A, B {
}
new MyObject extends Aggregate {
void foo() {}
void bar() {}
}
Notice the key is to declare the Aggregate as abstract.
Note that you can make a named local class that implements the two interfaces:
void method() {
class Aggregate implements A, B {
void foo() {}
void bar() {}
}
A a = new Aggregate();
B b = new Aggregate();
}
This save you from doing a class-level or top-level class declaration.
The result is called a local class. Local classes declared in instance methods are also inner classes, which means that they can reference the containing object instance.
Related
Here's something I quite understand:
abstract class A {
public void foo() {
System.out.println("a");
}
}
abstract class B extends A {
#Override
public abstract void foo();
public void bar() {
super.foo();
foo();
}
}
class C extends B {
#Override
public void foo() {
System.out.println("c");
}
}
public static void main(String[] args) {
new C().foo();
new C().bar();
}
new C().foo() prints c to the console, while new C().bar() prints a then c.
Calling super.foo() is illegal in the #foo() implementation of the C class.
I don't have a clear question, but if anyone could give a complete explanation of what is going on with the foo method, it may be interesting I think.
A is super class for B, so calling super.foo() inside B calls method defined in A, and calling foo() inside the same class will invoke its own implementation that should be delivered by any subclass.
You cannot use super.foo() within C class because it is defined as abstract in B and cannot be invoked directly.
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();
Java 8 introduces default methods to provide the ability to extend interfaces without the need to modify existing implementations.
I wonder if it's possible to explicitly invoke the default implementation of a method when that method has been overridden or is not available because of conflicting default implementations in different interfaces.
interface A {
default void foo() {
System.out.println("A.foo");
}
}
class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
public void afoo() {
// how to invoke A.foo() here?
}
}
Considering the code above, how would you call A.foo() from a method of class B?
As per this article you access default method in interface A using
A.super.foo();
This could be used as follows (assuming interfaces A and C both have default methods foo())
public class ChildClass implements A, C {
#Override
public void foo() {
//you could completely override the default implementations
doSomethingElse();
//or manage conflicts between the same method foo() in both A and C
A.super.foo();
}
public void bah() {
A.super.foo(); //original foo() from A accessed
C.super.foo(); //original foo() from C accessed
}
}
A and C can both have .foo() methods and the specific default implementation can be chosen or you can use one (or both) as part of your new foo() method. You can also use the same syntax to access the default versions in other methods in your implementing class.
Formal description of the method invocation syntax can be found in the chapter 15 of the JLS.
This answer is written mainly for users who are coming from question 45047550 which is closed.
Java 8 interfaces introduce some aspects of multiple inheritance. Default methods have an implemented function body. To call a method from the super class you can use the keyword super, but if you want to make this with a super interface it's required to name it explicitly.
class ParentClass {
public void hello() {
System.out.println("Hello ParentClass!");
}
}
interface InterfaceFoo {
public default void hello() {
System.out.println("Hello InterfaceFoo!");
}
}
interface InterfaceBar {
public default void hello() {
System.out.println("Hello InterfaceBar!");
}
}
public class Example extends ParentClass implements InterfaceFoo, InterfaceBar {
public void hello() {
super.hello(); // (note: ParentClass.super could not be used)
InterfaceFoo.super.hello();
InterfaceBar.super.hello();
}
public static void main(String[] args) {
new Example().hello();
}
}
Output:
Hello ParentClass!
Hello InterfaceFoo!
Hello InterfaceBar!
The code below should work.
public class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
void aFoo() {
A.super.foo();
}
public static void main(String[] args) {
B b = new B();
b.foo();
b.aFoo();
}
}
interface A {
default void foo() {
System.out.println("A.foo");
}
}
Output:
B.foo
A.foo
You don't need to override the default method of an interface. Just call it like the following:
public class B implements A {
#Override
public void foo() {
System.out.println("B.foo");
}
public void afoo() {
A.super.foo();
}
public static void main(String[] args) {
B b=new B();
b.afoo();
}
}
Output:
A.foo
It depends on your choice whether you want to override the default method of an interface or not. Because default are similar to instance method of a class which can be directly called upon the implementing class object. (In short default method of an interface is inherited by implementing class)
Consider the following example:
interface I{
default void print(){
System.out.println("Interface");
}
}
abstract class Abs{
public void print(){
System.out.println("Abstract");
}
}
public class Test extends Abs implements I{
public static void main(String[] args) throws ExecutionException, InterruptedException
{
Test t = new Test();
t.print();// calls Abstract's print method and How to call interface's defaut method?
}
}
Given:
I have two different projects legacy A and nextGen B.
There is the third project C which is shared between A and B.
Objective:
I have to do an averageCalculation() in the third project C. But the implementation is different for the projects A and B. Using the same method signature but different implementations, how do I create a design? Note: the project A and B should just call averageCalulation() the same method signature.
Project C
Interface I {
averageCalculation();
}
Class CClass implements I{
?<averageCalculation()-for A>
?<averageCalculation()- for B>
}
Project A
{
I i1 = new CClass();
i1.averageCalculation();
}
Project B
{
I i2 = new CClass();
i2.averageCalculation();
}
Is the above approach correct? if so how would i create two implementations of averageCalculation() in CClass?
Create two different classes that implement your interface, and use a different class in each project:
Project C
interface I {
averageCalculation();
}
class CClassForA implements I{
averageCalculation(){...} // for A
}
class CClassForB implements I{
averageCalculation(){...} // for B
}
Project A
{
I i1 = new CClassForA();
i1.averageCalculation();
}
Project B
{
I i2 = new CClassForB();
i2.averageCalculation();
}
I am not sure I understand your problem entirely but here is a solution. You can't change the legacy projects but you want to A and B to conform to some Interface I. You can do this by wrapping A and B in something that does conform to I and implement I with A and B's respective implementations.
public class Problem {
public static class A{
public int foo(){
return 3;
}
}
public static class B{
public int foo(){
return 5;
}
}
public interface TheFoo{
public int foo();
}
public static class AWrapper extends A implements TheFoo{
public int foo(){
return super.foo();
}
}
public static class BWrapper extends B implements TheFoo{
public int foo(){
return super.foo();
}
}
public static void main(String[] args){
//TheFoo[] myFoos = new TheFoo[]{new A(), new B()}; Won't work
TheFoo[] myFoos = new TheFoo[]{new AWrapper(), new BWrapper()};
for(TheFoo curFoo : myFoos){
System.out.println(curFoo.foo());
}
}
}
An interface is just a contract for classes that implement it to define. If a class needs two different implementations of a single method in an interface then you should consider redesigning your project
Why do you need CClass ? You can have a class in Project A implement I and another class in Project B doing the same.
EDIT : the compiler will not let you have two different implementations of the method with the same signature. You do have an option to overload it if that is what you want
public interface SomeInter
{
public void doSomething();
}
public class ImplClass implements SomeInter
{
#Override
public void doSomething() {
// TODO Auto-generated method stub
}
public void doSomething(String abc)
{
// TODO Auto-generated method stub
}
}
Hope this helps!!
I have
public class D extends B
{
public void method() {}
}
public class B
{
public void method() {}
public void anotherMethod() { method(); }
}
In the above, if you hold an instance of D, say d, d.anotherMethod() results in calling D.method.
Is there a syntax in Java to call B.method() from inside anotherMethod()?
No, there isn't. The derived class would have to contain a call to super.method().
If B wants to prevent subclasses from overriding method(), it should declare method() as final.
You still can call the super method by explicitly using super like this this:
public class D extends B{
public void method() {}
public void anotherMethod() { super.method(); }
}
The only thing that is required is for you to override anotherMethod().
Another way is thinking like this. You want anotherMethod to call B method() so:
public class D extends B{
public void methodInternal() {}
}
public class B{
public final void method() {
//...
methodInternal();
}
public void methodInternal() {}
public void anotherMethod() { method(); }
}
Here the user can create his own version of method() by overriding methodInternal(), but still the behavior of the original method() is intact.
You can make method() static in B and then call it as B.method() from the instance methods where it is needed (you may need to rename the static method if you want to use the name for the instance method).
At least that's what I do in similar situations.
Maybe you should also reconsider your design.