When Interface A defines Interface B in its method signature - java

... how can I restrict an implementation of A to use a certain implementation of B in the method signature?
Use Case
Here is a Unit interface and two enums that implement it:
public interface Unit { ... }
public enum ForceUnit implements Unit { ... }
public enum MassUnit implements Unit { ... }
Which is used by the Property interface:
public interface Property {
public void setUnit( Unit unit ); // for example
}
public class Force implements Property { ... }
public class Mass implements Property { ... }
Here I want to be able to enforce that:
Force uses only ForceUnit in the setUnit signature
Mass uses only MassUnit in the setUnit signature
When I try to do this, Eclipse complains:
The type Mass must implement the inherited abstract method Property.setUnit(unit)
And promptly suggests two quick fixes:
make the class abstract, which is not an option since I want to be able to do stuff like Mass mass = new Mass();
add the unimplemented methods with an #Override annotation. I don't know if this is the right fix, but to me this smacks of clumsiness.
Questions
What options do I have to achieve what I want? Would the use of generics help here?
Why does marking the class as abstract resolve the issue?

You can use generics
public interface Property<U extends Unit> {
public void setUnit(U unit ); // for example
}
public class Force implements Property<ForceUnit> {
#Override
public void setUnit(ForceUnit unit) { }
}
public class Mass implements Property<MassUnit> {
#Override
public void setUnit(MassUnit unit) { }
}
Note: This does mean you can still do
Property raw = new Mass();
raw.setUnit(ForceUnit.NEWTON); // ClassCastException
however this will cause a class cast exception as the compiler is unable to check the raw type at run time.
What you should do is
Property<Mass> raw = new Mass();
raw.setUnit(ForceUnit.NEWTON); // doesn't compile.
Why does marking the class as abstract resolve the issue?
Making the classes abstract means that setUnit(Unit) hasn't actually been implemented but for an abstract class this is ok.

Related

Java subclass implementation mandatory constructor

Is there any way in Java to enforce a subclass or interface implementation to have a constructor with a given signature?
Let's say that I´ve got either:
public interface MyInterface {
// any methods
}
or
public abstract class MyBaseClass {
// any abstract methods
}
Now, is it possible to do anything to require
public class MySubClass extends MyBaseClass {
public MySubClass(String s) { }
}
or
public class MySubClass implements MyInterface {
public MySubClass(String s) { }
}
to always have a constructor that takes a String as it´s only input parameter?
The obvious workaround is to create a factory interface with a method taking a String and inject it where required. Which is not what I would like to do.
Not really, the closest I think you can get is something like:
abstract class B {
public B(String s) {
}
}
public class A extends B {
public A(String s) {
super(s);
}
}
This forces A to implement a non default constructor which must call super(String) but can not prevent the following:
public class A extends B {
public A() {
super("");
}
}
There have been many times where I wished something like this existed, but sadly it doesn't. Even something like what David Soroko suggested wouldn't work because a subclass still wouldn't be forced to have a String constructor - it can just pass any String it likes to super. Simply put, there is no such thing within the Java syntax itself.
I suppose the closest one could get to such a capability is if someone built an annotation processor that allows you to use an annotation like #MustHaveUnaryConstructor(String.class) and then if any subclass does not have such a constructor, it causes compilation to fail and tells you which subclass broke the contract. But I haven't found such a thing and I don't know enough about annotation processing to build one myself. So TL;DR, no, you can't.

Provide implementation for abstract method but restrict visibility

I have a method in an abstract class that calls an abstract method, for which the subclasses must provide the implementation.
public abstract class AClass {
public void foo() {
...
fooToImplement();
...
}
// DON'T CALL THIS METHOD, ONLY PROVIDE IMPLEMENTATION!
protected abstract void fooToImplement();
}
I want to make sure that the subclasses don't call fooToImplement(), they should always use foo() instead. The behavior is something like a "private abstract" method, but that's not possible in Java.
Is there some alternative? Thanks!
If you don't want your subclasses to be able to call this method you could use strategy: Extract the behavior of the method into an interface and pass an implementation of this interface to the object. E.g.
IStrategy {
public void fooToImplement();
}
AClass {
public AClass(IStrategy impl) {...}
public void foo() {
...
strategy.fooToImplement();
...
}
}
Delegation instead of inheritance. In java 8 this would be a little bit easier.
If your implementation of IStrategy would need access to the data of the object AClass, you could try to implement it as an inner class.
The method has to be visible by your subclass if you want it to be overriden.
You have to use a class witch does not extends AClass as caller.
public class BClass extends ACLass {
#Override
protected void fooToImplement() {
System.out.println("override me im famous");
}
}
public class CClass {
private BCLass bInstance;
public void doSomething(){
bInstance.foo();
// !!! NO ACCESS TO fooImplement()
}
}
Since fooToImplement() needs to be visible to subclasses to be implemented there and there's no way to distinguish between "implement visibility" and "execution rights", you can't do this by inheritance.
You could however combine your object with another object that contains fooToImplement() by composition:
interface FooImplementation {
void fooToImplement(AClass a);
}
public abstract class AClass {
private final FooImplementation fooImpl;
protected AClass(FooImplementation fooImpl) {
this.fooImpl = fooImpl;
}
public void foo() {
...
fooImpl.fooToImplement(this);
...
}
}
That wouldn't prevent anyone from outside the class from using yourFooImpl.fooToImplement(yourAClass) however. To prevent this you could create a class that provides the information that fooToImplement() needs, but that can only be instanciated from within AClass:
interface FooImplementation {
void fooToImplement(AClass.AClassFooView a);
}
public abstract class AClass {
private final FooImplementation fooImpl;
protected AClass(FooImplementation fooImpl) {
this.fooImpl = fooImpl;
}
public class AClassFooView {
...
private AClassFooView() {
}
}
public void foo() {
...
fooImpl.fooToImplement(this.new AClassFooView());
...
}
}
But fooToImplement could pass the reference to AClassFooView to other classes...
However depending on the implementors of your class making absolutely sure in the documentation, that nobody should call fooToImplement() could also be an alternative.
Ultimately you have to trust the implementors, since there's also the the possibility of someone using reflection to get access to private members, reverse engeneering+changing+recompiling your class ect..
You can use AOP to this, for example add aspect #Before to fooToImplement() and check stacktrace of calling and throw IllegalArgumentException if fooToImplement() be called any method except foo(), something like:
if(!Thread.currentThread().getStackTrace()[1].getMethodName().equals("foo")) {
throw new IllegalArgumentException("You musn't call fooToImplement() directly"+
", using foo() instead");
}
However this way has two problem:
perfomance
runtime exception

Java Generics and Bounded parameters in subclasses

I'm trying to understand how to use generics in the form of a bounded type parameter in an interface. In this case, to avoid casting when using the bounded param in concrete implementations but I'm running into an issue. I will use the following example to illustrate my problem:
There's an interface and two concrete implementations
public abstract class Publication {
}
public class Newspaper extends Publication {
}
public class Newspaper extends Publication {
}
Then we have an interface representing a publishing house with two concrete implementations, one publishes magazine and the other newspapers
public interface Publisher {
public <T extends Publication >void publish(T publication);
}
Here are the two implementations
//DOES NOT COMPILE
public class MagazinePublisher implements Publisher{
#Override
public void publish(Magazine publication) {
//do something with the magazine, its already the type we need without casting
}
}
//COMPILES but a cast is required to get the type I want
public class NewsPaperPublisher implements Publisher{
#Override
public void publish(Publication publication) {
// Now I need to cast
Newspaper newspaper = (Newspaper)publication;
//Do some stuff here
}
}
The example maybe a bit contrived... I understand why the MagazinePublisher class doesn't compile: I'm trying to implement the method with a more specific class than defined by the contract of the publish method in the interface. So how do I user generics to avoid the cast in the NewsPaperPublisher class's publish() method?
You want to make the interface generic.
public interface Publisher <T extends Publication> {
void publish(T publication);
}
Then, instead of NewspaperPublisher and MagazinePublisher, you can just write Publisher<Newspaper> and Publisher<Magazine>.
Or if you want to provide different implementations depending on the type, you can write things like
public class NewspaperPublisher implements Publisher<Newspaper> {
#Override
public void publish(Newspaper publication) {
// do some stuff
}
}

Same method with different return types in abstract class and interface

Just extending the question..
Same method in abstract class and interface
Suppose a class implements an interface and extends an abstract class and both have the same method (name+signature), but different return types. Now when i override the method it compiles only when i make the return type same as that of the interface declaration.
Also, what would happen if the method is declared as private or final in the abstract class or the interface?
**On a side note. Mr. Einstein stuck to this question for an abominable amount of time during an interview. Is there a popular scenario where we do this or he was just showing off?
If the method in abstract class is abstract too, you will have to provide its implementation in the first concrete class it extends. Additionally, you will have to provide implementation of interface. If both the methods differ only in return type, the concrete class will have overloaded methods which differ only in return type. And we can't have overloaded methods which differ only in return type, hence the error.
interface io {
public void show();
}
abstract class Demo {
abstract int show();
}
class Test extends Demo implements io {
void show () { //Overloaded method based on return type, Error
}
int show() { //Error
return 1;
}
public static void main (String args[]) {
}
}
No, same method names and parameters, but different return types is not possible in Java. The underlying Java type system is not able* to determine differences between calls to the methods at runtime.
(*I am sure someone will prove me wrong, but most likely the solution is considered bad style anyways.)
Regarding private/final: Since you have to implement those methods, neither the interface method nor the abstract method can be final. Interface methods are public by default. The abstract method can't be private, since it must be visible in the implementing class, otherwise you can never fulfill the method implementation, because your implementing class can't "see" the method.
With Interfaces the methods are abstract and public by default ,
so they cant have any other access specifier and they cant be final
With abstract class , abstract methods can have any access specifier other than private and because they are abstract they cant be final
While overriding , the method signature has to be same ; and covariant(subclass of the declared return type) return types are allowed
A class cannot implement two interfaces that have methods with same name but different return type. It will give compile time error.
Methods inside interface are by default public abstract they don't have any other specifier.
interface A
{
public void a();
}
interface B
{
public int a();
}
class C implements A,B
{
public void a() // error
{
//implementation
}
public int a() // error
{
//implementation
}
public static void main(String args[])
{
}
}

abstract class with abstract fields and subclassing without casting

I created an abstract base class. It contains an object which should be extended by any subclasses:
public abstract class AbstractParent {
protected AbstractObject subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract AbstractObject createThisInYourExtendedClass();
}
the abstractObject:
public abstract class AbstractObject {
// ... some fields/methods that all subclasses need
}
What I want is to be able to use the extended field in the extended class without casting:
public class ExtendParent extends AbstractParent {
// .. some unique fields
public ExtendParent(){
super();
}
public ConcreteObject createThisInYourExtendedClass(){
return new ConcreteObject();
}
// what I want to do - no cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(this.subMePlz);
}
// what I end up doing - gotta cast
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println((ConcreteObject)this.subMePlz);
}
}
Would needing a comparator change how I should implement this? - I'm thinking a generic comparator for a list of the AbstractObjects that could be used by its subclasses.
It sounds like you need to make it generic:
public abstract class AbstractParent<T extends AbstractObject> {
protected T subMePlz;
// ... some fields that all subclasses need
public AbstractParent() {
this.subMePlz = createThisInYourExtendedClass();
}
public abstract T createThisInYourExtendedClass();
}
public class ExtendParent extends AbstractParent<ConcreteObject> {
...
}
Note that calling non-private methods within a constructor is usually a bad idea - the subclass won't have been fully initialized yet, which can make it difficult to reason about how much you can really rely on.
You have two options:
Abandon the project to declare the field in the superclass. Instead, add an internal abstract "getter" method to your superclass -- basically, AbstractParent should have a method abstract AbstractObject getSubMePlz().
Use generics to set the type of subMePlz in your subclass: define AbstractParent<T> to have a T for its subMePlz field.
Personally, I frequently find option 1 to be very pleasantly extensible -- for example, you can have another subclass that narrows the getSubMePlz() return type without yet declaring it, which can be advantageous.
Why not use this -
super.subMePlz
instead of this -
(ConcreteObject)this.subMePlz
That way, you won't need a cast.
You just could save a copy of the object in the subclass but with the correct class.
public class ExtendParent extends AbstractParent {
ConcreteObject concreteObject;
public AbstractObject createThisInYourExtendedClass(){
ConcreteObject concreteObject = new ConcreteObject();
return concreteObject;
}
public void doSomethingWithSubMePlzWithoutCastingIt() {
System.out.println(concreteObject);
}
...

Categories