Java (Processing 1.5.1): Fluent interface # multilevel inheritance via generics - java

I try to implement a fluent interface in my 2D game engine.
Simplified example of my implementation:
public class Sprite<T> {
protected float x = 0.0;
protected float y = 0.0;
public T setPosition(float x, float y) {
this.x = x;
this.y = y;
return (T)this;
}
}
public class Living<T extends Living> extends Sprite<Living> {
protected boolean alive = false;
public T setAlive(boolean alive) {
this.alive = alive;
return (T)this;
}
}
public class Entity<T extends Entity> extends Living<Entity> {
protected String name = null;
public T setName(String name) {
this.name = name;
return (T)this;
}
}
Entity entity = new Entity().setPosition(100, 200).setAlive(true).setName("Zombie");
I keep getting the error: "The function setAlive(boolean) does not exist."
I know, using my methods the other way round (in a more logical order) works:
Entity entity = new Entity().setName("Zombie").setAlive(true).setPosition(100, 200);
And I know that overwriting any parent setter functions in each and every child class would work:
public class Entity extends Living {
protected String name = null;
public Entity setPosition(float x, float y) {
return (Entity)super.setPosition(x, y);
}
public Entity setAlive(boolean alive) {
return (Entity)super.setAlive(alive);
}
public Entity setName(String name) {
return (Entity)super.setName(name);
}
}
But I want the interface to be as free/uncomplicated as possible for the 'end user' and the code to be as compact and clean as it gets.
I don't know if I just messed up the generics or my hole approach is completely wrong. I hope you can help. I am open to any advice. (Sorry for my bad english.)
Edit:
I already tested the following approach and it works for the Entity class.
public class Sprite<T> {
...
}
public class Living<T> extends Sprite<T> {
...
}
public class Entity extends Living<Entity> {
...
}
I forgot to mention, that I need to instantiate Sprite & Living too. For example:
Living living = new Living().setPosition(50, 50).setAlive(false);

This is a valiant attempt at the curiously recurring template pattern in Java. The problem is that you're mixing generics and raw types which means you aren't "closing the loop" of the pattern. For example your declaration of Living:
public class Living<T extends Living> extends Sprite<Living>
Should really be:
public class Living<T extends Living<T>> extends Sprite<T>
At some point you'll need to declare a "leaf" class that resolves T, otherwise you won't be able to instantiate and declare variables of these types without resorting to raw types or wildcards (which defeats the purpose of the pattern). For example:
public final class ConcreteEntity extends Entity<ConcreteEntity>
See my answer here for more details on implementing this pattern.

I think your class model is over complicated, you can pass generic parameter down to the child class and then declare it explicitly:
public class Sprite<T> {
...
}
public class Living<T> extends Sprite<T> {
...
}
public class Entity extends Living<Entity> {
...
}

Related

Java Returning Type of Child class (abstract)

I've been trying my best with some basic code, and I am completely stuck...
I have an abstract class "Piece":
public abstract class Piece {
private static int type;
public int getType() {
return type;
}
}
The "Pawn" is the Child:
public class Pawn extends Piece {
private static final int type = 1;
}
And now for the problem: When creating the Pawn with Pawn p = new Pawn();, p.getType() returns 0, not 1...
How can I fix this?
The problem is that you already have a variable declared in your abstract class. You shouldn't redeclare it in your subclass. Instead, set the abstract class's variable like this:
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
You should also declare the variable as protected so that subclasses can access it and refrain from making it static, since that will allow only one value for all subclasses:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
This code you write relies on an instance and not on a static context:
Pawn p = new Pawn();
p.getType();
A static final field is not designed to be inherited by child classes.
And creating a static final field in the child class with the same name as in the parent class doesn't allow to override it either.
1) So you should use an instance field and not a static field for the type field.
2) If you want to override the behavior of getType() in the child class, in fact you don't even need to use a field. Using a method should be enough.
In the base class :
public abstract class Piece {
public int getType() {
return 0;
}
}
In the child class :
public class Pawn extends Piece {
#Override
public int getType() {
return 1;
}
}
Here is one way. But you really need to read up on classes and abstract classes.
public abstract class Piece {
public int getType() {
return 0;
}
}
public class Pawn extends Piece {
public int getType() {
return 1;
}
}
Having a static variable in a class means that all instances of that class share the same value. I don't think that's what you intended.
Also, you can use the hierarchy of inheritance to your advantage by not redefining the getType() method.
Here is one of many ways to solve it:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
There are two problems with your approach.
The first is that Java does not support inheritance of static methods. Not that it couldn't have supported this - it's just a design choice. What this means is that any method of class Piece, which calls getType() - calls the Piece class' implementation of getType(), not a polymorphic call to getType() of whatever the actual subclass is.
The second problem is that you're sort of reinventing the wheel. Java has rich reflection facilities: You can use getClass() and instanceof for your check:
if(myObject instanceof Piece && myObject.getClass() != Piece.class) {
// do stuff
}
and of course you can make this a method of the piece class (no need to override it).

java mutant design pattern and compiler error 'Interface' cannot be inherited with different type arguments 'TypeA' and 'TypeB'

I am way over thinking this: What I am trying to do is [hopefully not reinvent the wheel and] come up w/ a [Android] Java eventing mechanism that allows subclasses to pre-define an arbitrary set of "features" with getters and setters that fire individual callbacks.
I think I am fusioning some combination of Command, Visitor, Decorator, Facade and Observer patterns here, and confusing myself along the way.
I have been programming for well over 20 years, but I feel like a n00b on this fairly simple problem! :(
I have searched SO for the compiler error and read many of the results, but I still haven't found a solution that works for me.
(How to make a Java class that implements one interface with two generic types? seems to be the most relevant one that I have found, but I also want to generically get the values and fire events to callbacks when they are set).
First, let the below mostly valid code speak for itself...
interface IFeature
{
}
interface IFeatureCallbacks<T extends IFeature>
{
boolean onChanged(Feature<T> c);
}
public static class Feature<T extends IFeature>
{
private Set<IFeatureCallbacks<T>> listeners = new LinkedHashSet<>();
public void addListener(IFeatureCallbacks<T> listener)
{
listeners.add(listener);
}
public void removeListener(IFeatureCallbacks<T> listener)
{
listeners.remove(listener);
}
protected void onChanged()
{
for (IFeatureCallbacks<T> listener : listeners)
{
listener.onChanged(this);
}
}
}
//
interface IFeatureA
extends IFeature
{
int getA();
}
interface IFeatureACallbacks
extends IFeatureCallbacks<IFeatureA>
{
}
public static class FeatureA
extends Feature<IFeatureA>
implements IFeatureA
{
private int a;
public void setA(int value)
{
a = value;
onChanged();
}
#Override
public int getA()
{
return a;
}
}
//
interface IFeatureB
extends IFeature
{
boolean getB();
}
interface IFeatureBCallbacks
extends IFeatureCallbacks<IFeatureB>
{
}
public static class FeatureB
extends Feature<IFeatureB>
implements IFeatureB
{
private boolean b;
public void setB(boolean value)
{
b = value;
onChanged();
}
#Override
public boolean getB()
{
return b;
}
}
//
interface IDeviceWithFeatureA
extends IFeatureA
{
}
interface IDeviceWithFeatureACallbacks
extends IFeatureACallbacks
{
}
public static class DeviceWithFeatureA
extends Feature<IDeviceWithFeatureA>
implements IDeviceWithFeatureA
{
FeatureA a = new FeatureA();
public void addListener(IDeviceWithFeatureACallbacks listener)
{
a.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
}
//
interface IDeviceWithFeatureB
extends IFeatureB
{
}
interface IDeviceWithFeatureBCallbacks
extends IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureB>
implements IDeviceWithFeatureB
{
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureBCallbacks listener)
{
b.addListener(listener);
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
The above code seems to work fine, albeit something about it smells a bit off.
The problem is when I try to do this:
interface IDeviceWithFeatureAAndFeatureB
extends IFeatureA, IFeatureB
{
}
/*
Compiler error:
'IFeatureCallbacks' cannot be inherited with different type arguments 'IFeatureA' and 'IFeatureB'
*/
interface IDeviceWithFeatureAAndFeatureBCallbacks
extends IFeatureACallbacks, IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureAAndFeatureB>
implements IDeviceWithFeatureAAndFeatureB
{
FeatureA a = new FeatureA();
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureAAndFeatureBCallbacks listener)
{
a.addListener(listener);
b.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
I am less interested in trying to figure out how to make what I am trying to do compilable, and I am more interested in what about my abuse of a pattern is way off base so that I can re-write it to be both simpler and compile.
You are abusing the basic "pattern" of OOP -- inheritance. The adage is that "favor composition over inheritance". Think in terms of "contains", instead of "is-a".
Take Zoo for example. A zoo is just a bunch of animals, right? So naturally, we may want to declare Zoo as subtype of Set<Animal>. Perhaps even have class Zoo extends HashSet<Animal>.
However, that is likely a wrong design. A zoo is actually a lot of things. It contains a set of animals, sure; but it also contains a set of people (as workers, not exhibits (although...) ). So it's better to
class Zoo
Set<Animal> animals(){ ... }
Set<Person> workers(){ ... }
Anywhere we need to treat a zoo as a set of animals, just use zoo.animals(); think of it as a type cast, or projection. We don't need inheritance here.
In your design, you have too many types; what's worse, too many type relationships. It seems that you simply need one generic class that reads/writes value of T, and contains listeners of T
class Feature<T>
T value;
// getter
// setter
Set<ChangeListener<T>> listeners;
interface ChangeListener<T>
void onChange(T oldValue, T newValue)
A device contains a bunch of features
class SomeDevice
Feature<Integer> featureA = new Feature<>();
Feature<Boolean> featureB = new Feature<>();
That's it. You can operate on feature A of the device by operating on itsfeatureA.

How To Cast An Inherited Encapsulated Property To Expose Methods Of Subclass - Java

In Java I have an abstract base class, let's say WrapX, which contains a property of a type, say X (think Decorator DP). This class presents a method to call a specific method on the encapsulated X:
public abstract class WrapX{
protected X instance;
public WrapX(X x){
this.instance = x;
}
public void foo(){
instance.foo();
}
}
public class X {
public void foo(){
System.out.println("foo");
}
}
There is then a class called Y that extends from X and provides an additional method:
public class Y extends X {
public void bar(){
System.out.println("bar");
}
}
Then naturally I have created WrapY that can be used as a decorated type over the type Y:
public class WrapY extends WrapX{
...
public void bar(){
instance.bar();
}
}
So herein lies the issue. WrapY has inherited the instance property of type X from its parent WrapX. As far as Eclipse is concerned, instance is of type X and so will complain that it contains no method .bar().
Fair enough of course, but how then in this subclass can we implicitly cast the instance to an instance of Y (a valid subclass of the initial type X)... WITHOUT the need for explicit cast ascriptions littering the code, or variable shadowing?
If I just had this in the constructor:
public WrapY(Y y){
this.instance = y;
}
Eclipse still complains that .bar() is not a method of type X because I guess it cannot infer for certain that WrapY(Y y) will be used prior to construct the WrapY instance:
public void bar(){
instance.bar(); // ERROR
}
Here is the current approach I have, littered with casts:
public WrapY(Y y){
(Y)instance = y;
}
public void bar(){
((Y)instance).bar();
}
I haven't come across this particular type of architectural problem in my experience before, file it under 'Decorator-Based-Inheritance-Type-Casting'(!)... Please enlighten me as to how I can model this in a better way.
Another issue is that, if in future someone extends WrapY, the type of instance their class inherits will be the natural (uncasted) type of X, when they may reasonably assume it should be of type Y.
Thanks
You could make your Wrap class generic, for example:
public abstract class Wrap<T extends X>{
protected T instance;
public Wrap(T x){
this.instance = x;
}
public void foo(){
instance.foo();
}
}
public final class WrapY extends Wrap<Y> {
public WrapY(Y y) {
super(y);
}
public void bar(){
instance.bar();
}
}
Then for instances of WrapY, instance will be a Y.
Update:
If you want to inherit from WrapY, too (and address your last issue of the wrapped type being the most appropriate), do:
public class WrapY<U extends Y> extends Wrap<U> {
public WrapY(U y) {
super(y);
}
public void bar(){
instance.bar();
}
}

Abstract class can't be instantiated but can have constructor - little confusing, please explain [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Why do abstract classes in Java have constructors?
abstract class constructors?
We know abstract class can't be instantiated but on the other hand it can have constructor. Please explain why abstract class can have a constructor ? How compiler handles this situation?
The constructor of an abstract class is used for initializing the abstract class' data members. It is never invoked directly, and the compiler won't allow it. It is always invoked as a part of an instantiation of a concrete subclass.
For example, consider an Animal abstract class:
class Animal {
private int lifeExpectency;
private String name;
private boolean domestic;
public Animal(String name, int lifeExpectancy, boolean domestic) {
this.lifeExpectency = lifeExpectancy;
this.name = name;
this.domestic = domestic;
}
public int getLifeExpectency() {
return lifeExpectency;
}
public String getName() {
return name;
}
public boolean isDomestic() {
return domestic;
}
}
This class takes care of handling all basic animal properties.
It's constructor will be used by subclasses, e.g. :
class Cat extends Animal {
public Cat(String name) {
super(name, 13, true);
}
public void groom() {
}
}
This is probably not the best explanation but here it goes. Abstract classes enforce a contract much like an interface but can also provide implementation. Classes that inherit from the abstract class also inherit the implemented functions and depending on the language you can override the default implementation as needed.
Say you have abstract class A:
abstract class A {
private int x;
public A(int x) {
this.x = x;
}
public int getX() {
return x;
}
}
Notice, that the only way to set x is through the constructor, and then it becomes immutable
Now I have class B that extends A:
class B extends A {
private int y;
public B(int x, int y) {
super(x);
this.y = y;
}
public int getY() {
return y;
}
}
Now B can also set x by using super(x) but it has on top of that an immutable property y.
But you can't call new A(5) since the class is abstract you need to use B or any other child class.
Abstract class can have constructor that can be called in derived classes. So usually constructor is marked as protected in abstract class.

Inheritance, Generics and Casting in Java

I have two classes which both extends Example.
public class ClassA extends Example {
public ClassA() {
super("a", "class");
}
...
}
public class ClassB extends Example {
public ClassB() {
super("b", "class");
}
...
}
public class Example () {
public String get(String x, String y) {
return "Hello";
}
}
So thats all very well. So suppose we have another class called ExampleManager. With example manager I want to use a generic type and consequently return that generic type. e.g.
public class ExampleManager<T extends Example> {
public T getExample() {
return new T("example","example"); // So what exactly goes here?
}
}
So where I am returning my generic type how do i get this to actually work correctly and cast Example as either classA or classB?
Many Thanks
You can't use a generic type to instantiate new object (i.e. you can't do new T(params)).
When you are creating a concrete instance of object (that is, you use new), you have know the actual implementing class, you can't use a generic type.
What are you actually trying to achieve? How do you decide whether you want to create ClassA or ClassB?
Try this:
public class ExampleManager {
public ClassA createClassA() {
return new ClassA("example","example");
}
public ClassB createClassB() {
return new ClassB("example","example");
}
}
or this:
public class ExampleManager {
public Example createExample() {
if(a == b) {
return new ClassB("example","example");
}
return new ClassB("example","example");
}
}
As others have said, you can't use new to create a new instance of an unknown type. Without using reflection, you could make ExampleManager an abstract superclass of factories.
public abstract class ExampleManager<T extends Example> {
public abstract T getExample(String x, String y);
}
public class ClassAManager extends ExampleManager<ClassA> {
public ClassA getExample(String x, String y) {
return new ClassA(x, y);
}
}
public class ClassBManager extends ExampleManager<ClassB> {
public ClassB getExample(String x, String y) {
return new ClassB(x, y);
}
}

Categories