First, sorry for imperfection in my wording, just let me know if there are unclear points.
While I am building the class structure of a java application, I wonder if there are the known best practices that I've not found yet in my case.
For example, There are A, B, C and more classes specifying device types, and each device has a tokenizer, parser, and compiler.
First, I have four interfaces like these.
interface Device {
public void x();
public int y();
public String z();
...
}
interface Tokenizer {...}
interface Parser {...}
interface Compiler {...}
And, the actual concrete classes are,
public class ADevice implements Device {...}
public class BDevice implements Device {...}
public class CDevice implements Device {...}
class ATokenizer implements Tokeninzer {...}
class BTokenizer implements Tokeninzer {...}
class CTokenizer implements Tokeninzer {...}
class AParser implements Parser {...}
...
class ACompiler implements Compiler {...}
...
Additionally and importantly, the "Device" classes and its interface are public so that will be contained in a stub lib. Anything else will only be included in the actual library and not visible to users who generate scripts by referring to the API.
Here is my question, (Long introduction :[ )
How to achieve the cohesion between each type and its corresponding interfaces.
In more detail, is there a way to determine whether they are paired right, between each type of device interface and its corresponding tokenizer, parser, or compiler interface in a compile time?
For example, there is a manager class that uses "Device" objects and "Tokenizer", "Parser", and "Compiler" objects. As you can see, "ADevice" objects can only be a pair with "ATokenizer", "AParser", or "ACompiler". However, if we define their type of the device objects from the interface, then there is no way we can tell if those objects are corresponding to the right "Tokenizer", "Parser", or "Compiler" object, except that "instanceOf" operator in a run time.
For instance, "ADevice" can be matched with "BTokenizer", "CParser", and so forth, and that will not generate the compile error.
I hope that I would like to hear a good answer or redirect to references.
One solution would be to paramaterize your interfaces:
interface Tokenizer<D extends Device> { ... }
interface Parser<D extends Device> { ... }
interface Compiler<D extends Device> { ... }
Then your implementations would be:
class ATokenizer implements Tokeniser<ADevice> { ... }
class BTokenizer implements Tokenizer<BDevice> { ... }
class CTokenizer implements Tokenizer<CDevice> { ... }
class AParser implements Parser<ADevice> { ... }
.
.
.
class ACompiler implements Compiler<ADevice> { ... }
You could then have a method in your Manager class that restrict them to the same type:
public <D extends Device> void doStuff(Tokeizer<D> tokenizer, Parser<D> parser, Compiler<D> compiler) { ... }
The compiler would then only allow it to be used as you descibe:
doStuff(new ATokeizer(), new AParser(), new ACompiler()); // works
doStuff(new ATokeizer(), new AParser(), new BCompiler()); // compiler error
Have you thought about generic interfaces?
With interface like below:
public interface Parser<E extends Device> {
void parse(E device);
void parse(String someString);
}
You could create class like this:
public class AParser implements Parser<ADevice> {
#Override
public void parse(ADevice device) {
//parse...
}
#Override
void parse(String someString) {
//parse...
}
}
Related
... 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.
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
}
}
I have below classes and interfaces.
SuperInterface.java
public interface SuperInterface{/*some logic*/}
SubOneInterface.java
public interface SubOneInterface extends SuperInterface{/*some logic*/}
SubTwoInterface.java
public interface SubTwoInterface extends SuperInterface{/*some logic*/}
One.java
public class One{/*some logic*/}
Two.java
public class Two{/*some logic*/}
SubOne.java
public class SubOne extends One implements SubOneInterface{/*some logic*/}
AnotherSubOne.java
public class AnotherSubOne extends One implements SubTwoInterface{/*some logic*/}
SubTwo.java
public class SubTwo extends Two implements SubOneInterface{/*some logic*/}
AnotherSubTwo.java
public class AnotherSubTwo extends Two implements SubTwoInterface{/*some logic*/}
Now i have to write a class which will hold the implementation classes of both SubOneInterface and SubTwoInterface.
public class ClassesHolder{
private List<One> one;
private List<Two> two;
//setters and getters
}
Now ClassesHolder should accept all the objects(sub classes of One and Two) which implements either SubOneInterface or SubTwoInterface But not mix of both interfaces.
IF they try to populate the lists with mixed interface implementations then exception should be thrown.
How can i do that?
You can't easily exclude classes that implement a particular interface. If your contract requirement references SubOneInterface, then it'll accept classes that implement SubOneInterface, regardless of what else they implement.
Trying to do otherwise seems like a bad design. If your ClassesHolder contains a class implementing SubOneInterface, then that's how it will refer to that class, and any other functionality will be hidden, due to the additional interfaces not being referenced.
You could inspect your classes upon addition to th elist e.g.
public void addToListOfOnes(final SubOneInterface obj) {
if (obj instanceof SubTwoInterface) {
// throw an exception
}
}
but that seems very poor/counterintuitive. I would take a step back and look at your design again.
Have a look at my example below. If you could introduce another interface as the base type of your interfaces, this solution should work for your. Once instantiated, it will either except subtypes of One or subtypes of Two.
public class Example {
public static void main(String[] args) throws Exception {
ClassesHolder<One> ones = new ClassesHolder<One>();
ones.add(new SubOne());
ones.add(new SubSubOne());
}
}
interface Zero {}
interface One extends Zero {};
interface Two extends Zero {};
class SubOne implements One {};
class SubSubOne implements One {};
class SubTwo implements Two {};
class SubSubTwo implements Two {};
class ClassesHolder<V extends Zero> {
public <T extends V> void add(T item) {}
}
Using Class.isInterface() you can check if it belongs to a particular interface.
As per your requirement you want to check before adding to a list you are trying to check if a class is an Interface of SubOneInterface or SubTwoInterface But not mix of both interfaces.
Does that make sense?
I'm working with Google Web Toolkit, and I'm having problems implementing a generic interface. I'm not really familiar with generics, doing an upgrade on someone else's code here.
Here's what I want to do: I want to have an implementation of a generic callback interface that does some logging, and then subclass that implementation in order to handle specific callback scenarios.
The interface is something like this:
public interface AsyncCallback<T> {
void MethodFromAsyncCallback(T result);
}
The abstract and concrete implementations look something like this:
class CallbackBase implements AsyncCallback<Object> {
public abstract void doStuff(Object result);
public void MethodFromAsyncCallback(Object result) {
// IMPORTANT STUFF
// here are things I would like to do for all callbacks, hence the superclass.
// Then we do the subclass specific things.
doStuff(result);
}
}
class SpecificCallback extends CallbackBase
{
public void doStuff(Object result) {
Integer i = (Integer)result;
// do stuff with i
}
}
The callbacks are required to be fired from
public interface MyServiceAsync {
public void DoSomeThing(AsyncCallback<Integer>);
}
And then it all comes together in a call that looks like this:
MyServiceAsync myService = (MyServiceAsync)GWT.create(MyServiceAsync.class);
myService.DoSomeThing(new SpecificCallback());
And here's where we have a problem!
When the GWT.create() implements the interface I created, it demands that the type given to AsyncCallback is specified (matches a type elsewhere, outside the scope of this question), hence making DoSomething(AsyncCallback<Integer>) an Integer rather than an Object. This is beyond my control.
It complains that DoSomething() takes AsyncCallback<Integer>. I'm giving it something that inherits from something that is an AsyncCallback<Object>. I guess with generics, concepts of inheritance get somewhat broken?
So my question is this:
Either how can I mush this together so that DoSomething() will recognize that that SpecificCallback meets it's requirements,
or how can I structure the relationship between CallbackBase and SpecificCallback so that duplicate code is avoided, but SpecificCallback implements AsyncCallback<Integer> directly?
Thanks.
What I think you need to do is define CallbackBase like this:
abstract class CallbackBase<T> implements AsyncCallback<T> {
public abstract void doStuff(T result);
public void MethodFromAsyncCallback(T result) {
// general stuff (T is a subclass of Object)
doStuff(result);
}
}
Then you want your specific callbacks to be like this:
class SpecificCallback extends CallbackBase<Integer> {
public void doStuff(Integer result) {
// no need to cast
// do stuff with result
}
}
Then your DoSomething method, which accepts an AsyncCallback<Integer>, will accept a SpecificCallback.
(Pedantic sidenote: please start all methods with lowercase letters in Java)
Edit
For what it's worth, I'd suggest changing your design to use composition rather than inheritance. In this case, rather than using an abstract class CallbackBase and extending it, you'd use a concrete implementation of AsyncCallback<T> that might look something like this:
class GeneralCallbackWrapper<T> implements AsyncCallback<T> {
private final AsyncCallback<? super T> delegate;
public GeneralCallbackWrapper(AsyncCallback<? super T> delegate) {
this.delegate = delegate;
}
public void MethodFromAsyncCallback(T result) {
// general stuff here
delegate.MethodFromAsyncCallback(result);
}
}
So, say I have a simple enum and a class that uses it:
enum ThingType { POTATO, BICYCLE };
class Thing {
public void setValueType(ThingType value) { ... }
public ThingType getValueType() { ... }
}
But, in reality, I have lots of different classes that implement setValueType, each with a different kind of enum. I want to make an interface that these classes can implement that supports setValueType and getValueType using generics:
interface ValueTypeable {
public Enum<?> getValueType(); // This works
public <T extends Enum<T>> setValueType(T value); // this fails horribly
}
I can't change the class model because the classes are auto-generated from an XML schema (JAXB). I feel like I'm not grasping enums and generics combined. The goal here is that I want to be able to allow a user to select from a list of enums (as I already know the type at runtime) and set the value in a particular class.
Thanks!
Have you tried parameterizing the interface itself. Like:
class Thing<E extends Enum<? extends E>> {
public E getValueType();
public void setValueType(E value);
}
Then you have the subclass extend the one with right type:
class SomeSubClass implements Thing<ThingType> { ... }
enums are for when you have a fixed set of them. When you say that each implementation has its own, then you no longer have a fixed set, and how you are trying to use enums doesn't match your needs.
You might be interested in the request for Java to be able to have abstract enums.