How to refer to an instance that both extends and implements? - java

Let's say I have an abstract class, an extending class, and an interface like this:
public abstract class SuperClass {
...
public void foo() {...}
...
}
public class SubClass extends SuperClass implements MyInterface {...}
public interface MyInterface {
public void bar();
}
Note that I have a few subclasses of SuperClass implementing MyInterface, but not all of them.
Also let's say, I have another class with a constructor like this:
public class AnotherClass {
private SuperClass sc;
public AnotherClass(SuperClass superclass) {
sc = superclass;
}
...
}
My question now is, how would I be able to ensure that the given object in the constructor also implements MyInterface? I would need the object sc to be able to run both methods foo() and bar(). How can I accomplish this?

You could introduce another class to the hierachy:
public class NonImplementingSubClass extends SuperClass {...}
public class ImplementingSubClass extends SuperClass implements MyInterface {...}
All your subclasses that should implement your interface, will then extend ImplementingSubClass
public class SubClass extends ImplementingSubClass {...}
public class AnotherClass {
private ImplementingSubClass sc;
public AnotherClass(ImplementingSubClass superclass) {
sc = superclass;
}
...
}

You can use generics with intersection types,
public class AnotherClass<T extends SuperClass & MyInterface> {
private T sc;
public AnotherClass(T superclass) {
sc = superclass;
}
void fn(){
// use both methods
sc.foo();
sc.bar();
}
...
}
Now, AnotherClass will only allow types that are SuperClass and implement MyInterface.

public abstract class SuperClass implements MyInterface {
...
public void foo() {...}
...
}
public class SubClass extends SuperClass{}
public interface MyInterface {
public void bar();
}

Related

Lambda does not override an interface method from a separate file

When the functional interface is in the same file where lambda overrides it, it compiles fine.
package test.test;
public class Base {
public static void main(String[] args) {
Interface1 a = n -> System.out.println(2*n);
}
}
interface Interface1 {
void multiplyByTwo(int x);
}
When the functional interface is in a separate file and Base class implements it, it fails to compile with Base is not abstract and does not override abstract method multiplyByFour(int) in Interface3 error.
package test.test;
public class Base implements Interface3 {
public static void main(String[] args) {
Interface3 b = n -> System.out.println(4*n);
}
}
package test.test;
public interface Interface3 {
void multiplyByFour(int x);
}
Is here something wrong? Why does lambda not override the method in the second case?
Your first example has:
public class Base {
which does not implement Interface1
However, your second example has:
public class Base implements Interface3 {
which DOES implement Interface3
Not sure what you are trying to do here, but this is intended behaviour:
Interfaces
When a class implements an interface, you must implement all of the methods into the class
For example:
public interface IFoo {
void bar();
}
and class:
public class FooImpl implements IFoo {
// must implement bar method in IFoo
public void bar() {
System.out.println("I did something");
}
}
Having a lambda in the main method does not constitute implementing interface methods.
Fix?
Just delete implements Interface3, you don't need to implement the interface in your class to be able to use it.

How to call default interface method from another subclass?

Consider the following:
//Fooable.java
public interface Fooable {
public default void foo() {
System.out.println("Fooable::foo");
}
//Lots of other non-default methods...
}
//MyFooable.java
public class MyFooable implements Fooable {
#Override
public void foo() {
System.out.println("MyFooable::foo");
}
//implements other methods in Fooable...
}
//MyAdvancedFooable.java
public class MyAdvancedFooable extends MyFooable {
#Override
public void foo() {
Fooable.super.foo();
System.out.println("MyAdvancedFooable::foo");
}
public static void main(String[] args) {
new MyAdvancedFooable().foo();
}
}
As you can see, I want to call foo() in Fooable from MyAdvancedFooable (a subclass of MyFooable). However, when I try to compile, I get the following error:
MyAdvancedFooable.java:4: error: not an enclosing class: Fooable
Fooable.super.foo();
if I try MyAdvancedFooable extends MyFooable implements Fooable I get the following:
MyAdvancedFooable.java:4: error: bad type qualifier Fooable in default super call
Fooable.super.foo();
method foo() is overridden in MyFooable
How can I resolve this problem without having to create a new anonymous implementation of Fooable?
You can only call a method one level up so you would need
Fooable.super.foo();
in MyFooable, while just calling super.foo() in MyAdvancedFooable
You need to use just super.foo() or this.super.foo() as it is the parent of the object and not of the class as implied by Fooable.super.foo().

C++ Templates & Inheritance in Java

I have the following classes in C++
ParentClass
{
virtual int MyMethod();
}
class ExistingOne : ParentClass {...}
class ExistingTwo : ParentClass {...}
Now I would like to create a class that can extend either of the Existing classes and override a couple of their methods plus call a method in the Existing class under some conditions.
In C++ this is done using the following:
template< class BaseTemplate >
class MyClass : public BaseTemplate
{
int MyMethod()
{
DoSomething();
return BaseTemplate::MyMethod();
}
}
How is this done in Java?
So far I have
public abstract class ParentClass
{
public abstract int MyMethod();
}
public class ExistingOne extends ParentClass {...}
public class ExistingTwo extends ParentClass {...}
public class MyClass<T extends ParentClass>
{
public int MyMethod()
{
DoSomething();
return T.MyMethod(); //MyMethod must be statically defined?
}
}
Oh and lastly, I cannot modify the "Existing" or Parent class.
So is this the correct approach? How do I solve the static requirement?
In the C++ class definition, MyClass extends BaseTemplate. In the Java example, MyClass doesn't extend ParentClass, thus getting the expected problem.
In Java, just change the definition to:
public class MyClass<T extends ParentClass> extends ParentClass {
#Override
public int MyMethod() {
DoSomething();
return super.MyMethod();
}
}
Since MyMethod is abstract in ParentClass, this gives a compiler error. Instead, you would need to call MyMethod from an instance of ParentClass. This can be fixed by having a field T t inside MyClass:
public class MyClass<T extends ParentClass> extends ParentClass {
T t;
public MyClass(T t) {
this.t = t;
}
#Override
public int MyMethod() {
DoSomething();
return t.MyMethod();
}
}
Otherwise, using generics and extending ParentClass here won't have any sense at all.

determine whether a class's superclass implements a certain interface in java

Let me know if I am wrong but in my experience the instanceof call does not do what I need it to.
I have an abstract class that implements an interface and explicitly overwrites all methods in the interface. I have a subclass of this class. How can I tell if the subclass is an instanceof the interface?
public interface IAnimal {
public void eat();
}
public abstract class Dog implements IAnimal {
#Override
public void eat(){
//eat things
}
public abstract void bark();
}
public class Beagle extends Dog {
#Override
public void bark(){
//specific bark
}
}
So I have an instantiation of Beagle, how do i find out if it is an instance of IAnimal?
You can do a
IAnimal.class.isAssignableFrom(Beagle.class)
or
IAnimal.class.isAssignableFrom(someObjectInstance.getClass());
or even instance of works with interfaces
if (object instanceof IAnimal) { }

Abstract static factory method [getInstance()] in Java?

Of course, the following doesn't work in Java (no abstract static methods)...
public abstract class Animal {
public abstract static Animal getInstance(byte[] b);
}
public class Dog extends Animal {
#Override
public static Dog getInstance(byte[] b) {
// Woof.
return new Dog(...);
}
}
public class Cat extends Animal {
#Override
public static Cat getInstance(byte[] b) {
// Meow.
return new Cat(...);
}
}
What's the correct way of requiring that Animal classes have a static getInstance method that instantiates itself? This method should be static; a "normal" abstract method doesn't make sense here.
There is no way to specify in an abstract class (or interface) that an implementing class must have a particular static method.
It is possible to get a similar effect using reflection.
One alternative is to define an AnimalFactory interface separate from the Animal class:
public interface AnimalFactory {
Animal getInstance(byte[] b);
}
public class DogFactory implements AnimalFactory {
public Dog getInstance(byte[] b) {
return new Dog(...);
}
}
public interface Animal {
// ...
}
class Dog implements Animal {
// ...
}

Categories

Resources