I've seen a number of similar questions, but I don't think any were quite isomorphic, and none quite answered my question.
Suppose there are two interfaces, Tree and Named. Suppose further that I am given a method whose signature is
public <T extends Tree & Named> T getNamedTree();
How can I save the returned value to a variable, while still retaining the information that it implements both Tree and Named? I can't find a way of declaring a variable like
public <T extends Tree & Named> T mNamedTree;
and trying to cast it to an interface extending Tree and Named results in a class cast exception.
Assuming there is no third interface inheriting both Named and Tree, you cannot retain information about both interfaces statically. The compiler will require you to do a cast for one or the other, or for both:
Object namedTree = getNamedTree();
Tree asTree = (Tree)namedTree;
Named asNamed = (Named)namedTree;
Both casts should succeed.
If you have influence on the design of the API for the class, ask the authors to introduce an interface combining both Named and Tree, and returning an instance of that interface instead.
One possible solution would be to create another interface that extends both Tree and Named, and simply store that as the variable:
interface NamedTree extends Tree, Named {
}
public NamedTree namedTree;
public NamedTree getNamedTree();
What scope does the variable has to have?
There is three possibilities here.
A) the variable is just a local variable. In that case you nearly have already the answer... you just need to declare a type-parameter for the enclosing method for that type:
interface ItfA { Number propA(); };
interface ItfB { Number propB(); };
class Main {
private <T extends ItfA & ItfB> T getT() {
return null;
}
private <TT extends ItfA & ItfB> void doStuffWithT() {
TT theT = getT();
System.err.println(theT.propA());
System.err.println(theT.propB());
}
}
B) The scope is the live of an object and in that case is a member field.
The obvious answer is to make the class generic and the type-parameter would
have the same & constraint:
interface ItfA { Number propA(); };
interface ItfB { Number propB(); };
class Main<T extends ItfA & ItfB> {
T theT;
public void setT(T newT) {
theT = newT;
}
public void doStuffWithT() {
System.err.println(theT.propA());
System.err.println(theT.propB());
}
}
C) The scope is the live of the program, then the variable is a static class member. Here you don't have a generics solution.
C.1) Obviously if the class of the values that you are going to handle is known you would just use that class as the field type.
C.2) If not, you could constraint the code to handle only classes that implement an interface that extends ItfA and ItfB. That interface, say ItfAB. Would be to field type.
C.3) Now, what about not imposing that constraint? What about allow the code to handle objects from any class that implement those interfaces?
Unfortunately there is no a clean-cut solution to that:
C.3.a) You could either type the field Object and provide methods to access it as an ItfA or as a ItfB (basically hiding the casting).
C.3.b) Or, instead of holding directly a reference to the object, you use a proxy object that implements those interfaces and delegates calls to those interfaces methods to the original "T" typed value. The class for that proxy could itself be a generic accepting an arbitrary <T extends ItfA & ItfB> value (similar to the B. example above).
Related
public interface Shape {
void draw();
}
class Square implements Shape {
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
class ShapeFactory {
//use getShape method to get object of type shape
public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
public class FactoryPatternDemo {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
//get an object of Square and call its draw method.
Shape shape1 = shapeFactory.getShape("Square");
//call draw method of square
shape1.draw();
}
}
I got this code while learning design pattern and in this code, the return type of the getShape method is Shape (an interface).
So can an interface type be set as a return type of another method?
It is actually a good practice since you are programming for an Interface rather than Classes, what hides the details of the implementation and makes your code a lot easier to be maintained. Imagine this: you have an Interface X, two Classes that implement it (A and B) and another Class (C) that has a method called foo(). Since both classes A and B implement X, the return of foo() can be X what allows you to return both A or B objects.
In Java, when you have a Class that implements an Interface, an instance of that Class is also an instance of that Interface, that's why you can use an Interface as a return type.
To test what I said, you can create an Interface called MyInterface and a Class TestClass that implements MyInterface. If you create an instance of TestClass (let's say "myClass"), if you compile and run this code, you can check it:
if (myClass instanceof MyInterface) {
System.out.println("Hey, I'm an instance of MyInterface!");
}
So, can an interface type be set as a return type of another method?
Yes, in Java, one can always declare the return value of any method to be interface type. To quote the specification (emphasis mine):
An interface declaration introduces a new reference type whose members are classes, interfaces, constants, and methods. This type has no instance variables, and typically declares one or more abstract methods; otherwise unrelated classes can implement the interface by providing implementations for its abstract methods. Interfaces may not be directly instantiated.
In Java, there are two kinds of types:
Primitive types (byte, short, int, long, float, double, and boolean only)
Reference types (can be arbitrarily many)
Thus, when you have an interface Shape, you can declare methods whose return type (of Reference kind) is Shape. Since Shape is an interface, you can not direct instantiate it since it is abstract (if you do Shape abstractShape = new Shape(); you will get a compiler error: Shape is abstract; cannot be instantiated). In this regard, the return type declaration is analogous to variable type declaration.
There is nothing specific to the Factory design pattern here, although it is of particular importance in implementing a Factory. In general, whenever you believe that coding to interfaces is a good practice in a particular functionality, declaring return types to be interfaces enables that practice.
This is fundamental to the factory method pattern:
a factory method typically returns an interface type,
and the specific class that will be returned is a hidden implementation detail.
A classic example of this is the various factory methods in java.util.Collections, for example emptyList, singletonList, and so on.
These methods return List type, and the implementation is completely hidden.
Another good example is the factory methods in java.util.EnumSet,
with return type EnumSet, which is an abstract class.
Depending on the size of the underlying enum type, the methods will return a RegularEnumSet instance if the underlying enum type contains 64 or fewer elements (as most enum types do), or else a JumboEnumSet instance.
These are two different implementations of EnumSet. The exact type is irrelevant to clients, an implementation detail that can be hidden.
This is one way of abstraction, "Hiding Actual implementation".
I'd be extremely grateful if anyone could point out what I'm doing wrong.
I have an interface IDoubleSource, which I implement in a Person class. There is a LinearRegression class with a method that takes an IDoubleSource argument, but I will pass in the Person class.
As part of the IDoubleSource interface, an enum called Variables and a method called getDoubleValue(Enum) must be defined. Below, I show how I have done this in Person, and that the enum types are used to specify switch cases in the getDoubleValue() method.
The problems:
1) In LinearRegression, there is a method computeScore((MultiKeyCoefficient)Map, IDoubleSource), where the last argument is an interface. I cannot seem to access the Variables enum of the instance of the implementation of IDoubleSource within the computeScore method, despite having the interface imported into the LinearRegression class. It just doesn't register that an IDoubleSource has an enum called Variables (though I can call the getDoubleValue() method fine). Is there anything I'm obviously doing wrong, that prevents me accessing the enum Variables?
2) The getDoubleValue(Enum) method in Person class is designed to return a double value that depends on the value of the enum Variable passed to it. By looping through the keys (which are of String type) of a (MultiKeyCoefficient)Map in the LinearRegression class, I would like to use the keys to specify the enum values that I want as an argument to getDoubleValue(Enum) in the LinearRegression class (I would like getDoubleValue() to return several different values based on the Enum values it receives in the loop). However, I cannot use the (String) key in place of the expected enum as I get a ClassCastException java.lang.String cannot be cast to java.lang.Enum. How can I use the keys of the map to specify the Enums?
I'm not very familiar with using Enum types in Java, which may be a large part of my problem.
Now the code details:
I implement the following interface:
IDOUBLESOURCE INTERFACE
public interface IDoubleSource {
public enum Variables {
Default;
}
/**
* Return the double value corresponding to the given variableID
* #param variableID A unique identifier for a variable.
* #return The current double value of the required variable.
*/
public double getDoubleValue(Enum<?> variableID);
}
by creating the class:
PERSON CLASS
public class Person implements IDoubleSource {
public enum Variables {
nChildren,
durationInCouple,
ageDiff;
}
public Person() {
...
}
public double getDoubleValue(Enum<?> variableID) {
switch ((Variables) variableID) {
case nChildren:
return getNChildren();
case durationInCouple:
return (double)getDurationInCouple();
case ageDiff:
return getAgeDiff();
default:
throw new IllegalArgumentException("Unsupported variable");
}
In another package, I have a Class:
LINEARREGRESSION CLASS
public class LinearRegression
private MultiKeyCoefficientMap map = null;
public LinearRegression(MultiKeyCoefficientMap map) {
this.map = map;
}
....
public double score(IDoubleSource iDblSrc) {
return computeScore(map, iDblSrc);
}
public static double computeScore(MultiKeyCoefficientMap coeffMap, IDoubleSource iDblSrc) {
try {
final Map<String, Double> varMap = new HashMap<String, Double>();
for (Object multiKey : coeffMap.keySet())
{
final String key = (String) ((MultiKey) multiKey).getKey(0);
Enum<?> keyEnum = (Enum<?>) key; //Throws class cast exception
double value = iDblSrc.getDoubleValue(keyEnum);
varMap.put(key, value);
}
return computeScore(coeffMap, varMap);
} catch (IllegalArgumentException e) {
System.err.println(e.getMessage());
return 0;
}
}
}
public static double computeScore(MultiKeyCoefficientMap amap, Map<String, Double> values)
{
//Do some stuff
}
I'm very grateful that you've taken the time to read through this code. Please do let me know if you have any idea what I'm doing wrong!
Many Thanks and Best Wishes,
R
The key incorrect assumption you have is that the IDoubleSource.Variables enum is connected in some way to the Person.Variables enum. They're totally unrelated. (They just happen to have the same simple name.)
When a class (like Person) implements an interface (like IDoubleSource), that class is declaring that it will provide implementations of the (non-default) methods in that interface. Any inner classes, inner enums, or inner interfaces within the implemented interface are only relevant if they appear in the signatures of one of the interface methods that must be implemented.
So you could change your interface to:
public interface IDoubleSource {
public enum Variables {
Default;
}
public double getDoubleValue(Variables variableID);
}
... but then the only legal value to pass in to any implementation of getDoubleValue is Default -- implementors of IDoubleSource can't extend the set of allowed enum values.
I think what you really want to do is to declare that implementors of IDoubleSource must declare what type of enum they deal in:
public interface IDoubleSource<T extends Variables & Enum<T>> {
public interface Variables { }
public double getDoubleValue(T variableID);
}
What you're saying here is that an implementor of the getDoubleValue() method must use some enum type as its arg, and that type must also implement the Variables interface. (If there are no meaningful methods to put in that inner inteface, you can drop it for simplicity.)
Then your implementation would look like this:
public class Person implements IDoubleSource<PersonVariables> {
public enum PersonVariables implements Variables {
nChildren,
durationInCouple,
ageDiff;
}
public double getDoubleValue(PersonVariables variableID) {
switch (variableID) { //no cast necessary here!
case nChildren:
// ...
default:
// this is now really impossible
// if the rest of your program has no unsafe casts
throw new IllegalArgumentException("Unsupported variable");
}
}
}
The last trick, then, is to enhance the signature of your computeScore method to ensure that the iDblSrc argument uses the same enum type as those found in the map:
public static <T extends IDoubleSource.Variable & Enum<T>>
double computeScore(MultiKeyCoefficientMap<T,?> coeffMap,
IDoubleSource<T> iDblSrc);
Then the keys in the map won't be Strings at all, but rather instances of the right enum type.
There are multiple problems here:
An enum declared in an interface (or class) implemented (extended) by another class is NOT overridden by the implementing class. So what you have above is two completely different enums, which happen to have the same local name. But one is IDoubleSource.Variables, with one value: IDoubleSource.Variables.Default, and the other is Person.Variables, with three values, one of which is Person.Variables.nChildren
As the OP pointed out, you cannot simply cast a String (which presumably has a value matching the name of some enum) to an enum, and have it resolve to the expected enum value.
Given these two things, and that it seems you want to select different processing for subtype specific types of things, then at worst, you could pass the string key as an argument, and then vary the logic internally. But really, you have come up with a scheme where you need to have knowledge of the subtype in order to request appropriate (supported) processing. This does not allow for the type of decoupling that is intended when using an interface/implementing class(es). You may want to review the objectives here and work out a better design.
I have a set of operations. Every operation is a sequence of 2 steps. So, I have a base class which executes these two steps and all the operations extend this base class and provide the actual implementations for the two steps. Ex.
class Base {
Step1 step1;
Step2 step2;
B execute() {
A a = step1.perform();
B b = step2.perform(a);
}
//Set methods...
}
Here Step1 and Step2 are interfaces and one can change the implementations for them to do different things.
I have the following questions:
Every implementation of step2 takes instance of A as input which can also contain a derived type of A. So I need to do a downcast. Is it ok to do a downcast in this case or is there a better way to achieve this?
Some implementations of step2 may not return any value. Is it ok if we have an empty class just for the type hierarchy and other classes extend this class?
Question 1
Yes, that is ok. Every class which extends the class A or implements the interface A (what ever A is) will be "an instance of A". So it is perfectly OK to pass it to a method which needs an object of the type A. Nothing to worry about. This is how you should use interface and inheritance. There are different kind of "specializations" of the same super-class.
Question 2
This is a question of your API design. If you want that this method could return null, you can do this. But you should document it very good!
A very new possibility in Java 8 are so called Optionals. You can use them if a method could return null and you want to force the programmer to keep that in mind. That would be the cleanest (and recommended) way. You can find an example and a description at http://java.dzone.com/articles/optional-java-8-cheat-sheet. Basically you would say that your method perform of the class Step2 will return an Optional instead of the type:
interface Setp2 {
public Optional<B> perform(A a);
}
// the optional will wrap the actual result which could be null
// since Java 8
Optional<B> b = step2.perform(a);
It sounds like you should use generics:
interface Step1<T extends A> {
T perform(T a);
}
interface Step2<T extends A, U extends B> {
U perform(T a);
}
class Base<T extends A, U extends B>>{
Step1<T> step1;
Step2<T, U> step2;
B execute() {
T a = step1.perform();
U b = step2.perform(a);
}
//Set methods...
}
Regarding returning "nothing", the best way is to return null.
I am looking at the Interface chapter provided on the Java website
Using Interface as a type
So my understanding was that the whole point of interface is that it is like a class but it's not possible to form objects from it, but this page says how to use interface as a data type. the line Relatable obj1 = (Relatable)object1; seems to create an object of type Relatable which is an interface. Although I must say that the new keyword has not been used here, thus not really creating a reference to an object of type Relatable. Is that really the cause for this line NOT creating an object of type Relatable?
Again, it further says
If you make a point of implementing Relatable in a wide variety of
classes, the objects instantiated from any of those classes can be
compared with the findLargest() method—provided that both objects are
of the same class.
What does this mean? Does this mean anything that implements Relatable can call findLargest()? If it's so, why does it say provided that both objects are of the same class?
----- EDIT -----
From the previous chapters of this tutorial:
Definition of relatable:
public interface Relatable {
// this (object calling isLargerThan)
// and other must be instances of
// the same class returns 1, 0, -1
// if this is greater // than, equal
// to, or less than other
public int isLargerThan(Relatable other);
}
Using relatable as a type:
public Object findLargest(Object object1, Object object2) {
Relatable obj1 = (Relatable)object1;
Relatable obj2 = (Relatable)object2;
if ((obj1).isLargerThan(obj2) > 0)
return object1;
else
return object2;
}
----- EDIT 2 -----
In the chapter on anonymous classes, it does this:
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
.
.
.
HelloWorld englishGreeting = new EnglishGreeting();
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
So how does this work?
the line Relatable obj1 = (Relatable)object1; seems to create an object of type Relatable
No. This line creates a reference (obj1) of type Relatable and assigns it to object1. In order for this to work, object1 has to be cast to the (interface) type Relatable.
No new objects are being created here.
Does this mean anything that implements Relatable can call findLargest()?
Yes.
If it's so, why does it say provided that both objects are of the same class?
It has to do with the implementation of isLargerThan(). Since any class implementing the Relatable interface can't know anything about other classes implementing it, they can't do meaningful comparisons with other classes. Therefore, in order for this to work, both objects need to be of the same class.
Response to EDIT 2
So how does this work?
Instead of first defining a class and then creating an instance of it, as in the case with the EnglishGreeting, the frenchGreeting is created on the fly. What happens under the cover is that a new class implementing HelloWorld is created, just like in the english case, only this time it is anonymous (you never get to give it a name). It is just a convenience shortcut for those times when you need a one-time implementation of an interface.
Interface types belong to the category of reference types in java. You can never instantiate an interface, but it can be assigned references to any of the objects of classes which implement it:
A variable whose declared type is an interface type may have as its
value a reference to any instance of a class which implements the
specified interface.
Interfaces are like behaviors. If a class happens to implement an interface, lets say Serializable, this adds a behavior to the class, which is, the class can be serialized.
This helps you introduce abstraction in your code. For example lets assume that you need a method in one of your utility classes which will be responsible for the actual job of serialization. Without interfaces you will end up writing a lot of methods, one for each object type that you want to serialize. Now imagine if you asked each of those objects to take care of their serialization themselves (by implementing a serialize method declared in the interface they implemented). With such implementation you need to write only one utility method for serialization. This method can take an argument of Serializable type, and instances of any class implementing this interface can be passed to the method. Now within the method you only need to invoke the serialize method on the interface variable. At runtime this will result in actual object's serialize method getting invoked.
Hope I was able to keep it simple.
Interface in Java is a mutual structure for classes that implement the interface, so the classes benefit from the methods/other member of that interface in their own way, which is called polymophism,
interface A
{
// method header only declared here, so implementation can vary between classes
public int foo();
}
class B implements A
{
public override String foo()
{
return "Class B";
}
}
class C implements A
{
public override String foo()
{
return "Class C";
}
}
so you can call foo() both from class B and C but they will react differently since they implement that method in their own way
An interface is just a class that defines the behaviour of an object, but not the underlaying implementation of it.
By making Relatable obj1 = (Relatable)object1; you are just casting the object1 to a Relatable type, and therefore you can call any of the methods defined in the Relatable interface
To your first question about Relatable obj1 = (Relatable)object1;:
A simple Relatable obj1; will not create an instance of Relatable, but specifies that any object assigned to it must be of a type implementing the Relatable-interface.
Therefore any object that is to be cast, must be of a type implementing the Relatable-interface.
I have a tree structure, where some nodes must contain only objects implementing particular interface. But there is interfaces extending that interface, and objects, implementing them, should not be contained in nodes.
So i need to check if object implements strictly particular interface.
public interface IProcessCell {...}
public interface IMethodCell extends IProcessCell {...}
IProcessCell processInstance = new IProcessCell() {...}
IMethodCell methodInstance = new IMethodCell() {...}
/** Method implementing desired check */
public boolean check(IProcessCell instance) {...}
Method check must return true for processInstance, but false for methodInstance
You can use http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getInterfaces()
but to me the thing you are trying to do is like patching up badly written app. To me, the better way is creating a new interface (which only desired object will implement) and making the "tree structure" nodes require that particular interface.
You can get the list of implemented interfaces using getInterfaces.
Assuming you already casted your instance to the desired interface, you just have to test that yourInstance.getClass().getInterfaces().length==1
Class implements the getInterfaces() method. It returns a Class[]. Using this you could iterate and do a comparison until found or not found.
http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getInterfaces()
You can do a getClass().getInterfaces() on the node, then iterate through the returned classes and check how many are assignable from the particular interface you care about. So if you have:
interface A {
}
interface B extends A {
}
class NodeA implements A {
}
class NodeB implements B {
}
If you're looking for a node instance that just implements A you should be able to do:
new NodeA().getClass().getInterfaces();
new NodeB().getClass().getInterfaces();
and in each case check that 1) One of the interfaces is A, and 2) A.class.isAssignableFrom(interface) returns false for the other returned interfaces.