Im trying to create an instantiate a generic class called "MultipleBoundsClass" that has multiple bounds - a class called "OrderedPair" and an interface called "Pair"(which Ordered Pair implements).
Ive tried removing the interface boundary and that let me compile. But I dont know why that worked, and how Id get it to successfully with the interface boundary included.
public interface Pair<K, V>
{
public K getKey();
public V getValue();
}
public class OrderedPair<K, V> implements Pair
{
private K key;
private V value;
public OrderedPair(K key, V value)
{
this.key = key;
this.value = value;
}
public K getKey()
{
return key;
}
public V getValue()
{
return value;
}
}
class OrderedPair {}
interface Pair {}
public class MultipleBounds<T extends OrderedPair & Pair>
{
private T t;
public MultipleBounds(T t)
{
this.t = t;
}
public T getPair()
{
return t;
}
}
public static void main(String[] args)
{
OrderedPair<String, Integer> p1 = new OrderedPair<>("even", 8);
MultipleBounds<OrderedPair> myPair = new MultipleBounds<OrderedPair>(p1);
}
I get the error "type argument OrderedPair is not within bounds of type-variable T". Bounded types restrict the arguments a generic parameter can be, to the class you define and its subclasses, so why is the type OrderedPair not within bounds of itself when the interface is included as a present boundary?
I want to provide an example of how you might be using multiple bounds. It is freaky a lot, but may help to understand things.
Suppose we have a Container, and we are able to put something in.
abstract class Container {
private Object content;
public void put(Object object) { this.content = object; }
public Object get() { return content; }
}
Then, there are interfaces to define some properties for those containers. They may be Rollable and/or Inflammable.
interface Rollable { void roll(); /* rolls somehow */ }
interface Inflammable { void burnItself(); /* burns somehow */ }
Then, we define concrete Container classes: a CardboardBox, a GiftBox, a MetalBarrel and a WoodBarrel, and implement interfaces according to their properties:
class CardboardBox extends Container implements Inflammable {
#Override
public void burnItself() { /* omit implementation */ }
}
class GiftBox extends Container implements Rollable, Inflammable {
#Override
public void burnItself() { /* omit implementation */ }
#Override
public void roll() { /* omit implementation */ }
}
class MetalBarrel extends Container implements Rollable {
#Override
public void roll() { /* omit implementation */ }
}
class WoodBarrel extends Container implements Rollable, Inflammable {
#Override
public void burnItself() { /* omit implementation */ }
#Override
public void roll() { /* omit implementation */ }
}
Now, the real bizarre. Suppose you want to create a Stock, where all the things must be Rollable. And Inflammable. Because you want to roll all your containers inside and to be able to burn one of them. You define a Stock:
class Stock <T extends Container & Rollable & Inflammable> {
private List<T> containers;
void addContainer(T container) { containers.add(container); }
void rollAllContainers() { containers.forEach(Rollable::roll); }
void burnContainer(int index) { containers.get(index).burnItself(); }
}
And then you are able to create one of those. You are not tied to Container type; just to its properties - as they are defined by interfaces.
public static void main(String[] args) {
Stock<GiftBox> giftBoxStock = new Stock<>();
GiftBox giftBox = new GiftBox();
giftBox.put("a gift");
GiftBox giftBox1 = new GiftBox();
giftBox1.put("another gift");
giftBoxStock.addContainer(giftBox);
giftBoxStock.addContainer(giftBox1);
giftBoxStock.rollAllContainers();
giftBoxStock.burnContainer(0);
Stock<WoodBarrel> woodBarrelStock = new Stock<>();
WoodBarrel woodBarrel = new WoodBarrel();
woodBarrel.put("wine");
WoodBarrel woodBarrel1 = new WoodBarrel();
woodBarrel1.put("gas");
woodBarrelStock.addContainer(woodBarrel);
woodBarrelStock.addContainer(woodBarrel1);
woodBarrelStock.rollAllContainers();
woodBarrelStock.burnContainer(1);
}
Related
I'm probably going about this in the most complicated way, but I'm hoping what I'm trying to do makes sense here.
Suppose I have some set of unrelated, generated classes and I want to Decorate them to create some kind of common API. So something like:
public abstract class GeneratedDecorator<T> {
private T generated;
public T getGenerated() { return generated; }
public void setGenerated(T generated) { this.generated = generated; }
public abstract String getString();
public static class ClassA extends GeneratedDecorator<GeneratedClassA> {
#Override
public String getString() { return getGenerated().getThisString(); }
}
public static class ClassB extends GeneratedDecorator<GeneratedClassB> {
#Override
public String getString() { return getGenerated().getADifferentString(); }
}
}
Now, to use this new fancy class I just say:
GeneratedDecorator.ClassA a = new GeneratedDecorator.ClassA();
a.setGenerated(myGeneratedInstanceA);
a.getString();
Ok so far so-so ... but now I want to manage an array of these Decorators.
So let's try:
public abstract class DecoratorBundle<T extends GeneratedDecorator> {
private static final int MAX_ROWS = 10;
private T[] bundle;
DecoratorBundle() { bundle = createBundle(); }
public String getString(int index) { return bundle[index].getString(); }
public void setRow(??? generated, int index ) {
//check index of bundle, if null create a new instance of appropriate type and set bundle[index] = new instance
//call setGenerated on instance at index
}
protected abstract T[] createBundle();
public static class ClassA extends DecoratorBundle<GeneratedDecorator.ClassA> {
#Override
protected GeneratedDecorator.ClassA[] createBundle() {
return new GeneratedDecorator.ClassA[MAX_ROWS];
}
}
public static class ClassB extends DecoratorBundle<GeneratedDecorator.ClassB> {
#Override
protected GeneratedDecorator.ClassB[] createBundle() {
return new GeneratedDecorator.ClassB[MAX_ROWS];
}
}
}
Here's where I'm stuck ... I want this DecoratorBundle to have a setRow(??? generated, int index) where the parameter is of the GeneratedDecorator's type (i.e, GeneratedClassA or GeneratedClassB). Seems like type erasure will probably make this impossible, but it would be really nice to have this DecoratorBundle class to completely manage it's bundle array. It currently is able to instantiate the array, but I want some way for it to create a new GeneratedDecorator-type and assign it in a setRow method.
If I'm going about this completely wrong then I would love to hear another idea.
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.
I frequently find myself wanting to write generic class definitions of the form
public class Foo<ActualType extends Foo<ActualType>>
For example in a setup like this:
public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}
public class Foo<ActualType extends Foo<ActualType>> {
private final List<ChangeHandler<ActualType>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<ActualType> handler) {
handlers.add(handler);
}
#SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<ActualType> handler: handlers)
handler.onChange((ActualType) this);
}
}
public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}
public static void main(String[] args) throws IOException {
Bar bar = new Bar();
bar.addChangeHandler(new ChangeHandler<Bar>() {
#Override
public void onChange(Bar source) {
// Do something with the changed object
}
});
}
The change-event here is just an example. This is more of a general problem that I'm having whenever I would like to allow a super-class to provide functionality that is "individualized" to each specific sub-class (not sure how to phrase this better... in the example above the "individualization" is the fact that the ChangeHandler is called with an object of the actual sub-type (Bar) not with the type of the super-class (Foo) that is calling the handler).
Somehow this approach seems a bit messy to me. And it actually allows for potential issues since nothing prevents me from then defining:
public class Baz extends Foo<Bar> { /* ... */ }
Is there a cleaner alternative?
The holy grail would be some type parameter that is always defined to contain the current class, like a static version of this.getClass() that would allow me to write something like this instead:
public class Foo {
private final List<ChangeHandler<this.Class>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<this.Class> handler) {
handlers.add(handler);
}
protected void reportChange() {
for (ChangeHandler<this.Class> handler: handlers)
handler.onChange(this);
}
}
Where this.Class would be equal to Bar for classes of type Bar.
It is a really abstract problem. In my opinion the short answer to "how to make this cleaner" is: only use generics where it is needed.
public class List<T extends List<T>>
What is this trying to express (substituted)? A list which only allows to hold (T extends) other lists which themselves hold Ts (List) which as we know from before are Lists which only allow to hold ... and so on. Kind of circular, I don't see how you would end up with something like that?
public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}
Why do you want to use generics here? If you want to have a change handler which can handle several resource types, then you can either create a super class from which all actual sources inherit or you create an interface which is implemented by the sources. Like that you can exactly specify what is exposed by the sources. Alternatively the source can create a source object when notifying instead of passing "this" (then it is more like a message). For example:
public interface ChangeHandler {
public void onChange(Source source);
}
public abstract class Source {
private List<ChangeHandler> handlers;
protected int nr;
public Source(int nr) {
this.nr = nr;
}
public abstract Something getSomething();
public String toString() {
return "SRC" + nr;
}
...
private notify(int index) {
handlers.get(i).onChange(this);
}
}
public class Foo extends Source {
public Foo(int nr) {
super(nr);
}
public String toString() {
return super.toString() + "Foo";
}
public Something getSomething() {
return new Something();
}
}
You never need to cast... or do you? I'm not sure if I understand the problem.
I would recommend that we simply use <This> to represent the "self type". No need for bound, since it looks complicated, doesn't deliver the intention, and cannot enforce the constraint anyway.
public class Foo<This> {
private final List<ChangeHandler<This>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<This> handler) {
handlers.add(handler);
}
#SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<This> handler: handlers)
handler.onChange( (This)this );
}
}
Notice the cast (This)this.
See also Java generics: Use this type as return type?
I never use type parameters to pass "ActualType" because then it is impossible to extend the object:
public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}
public class Bar2 extends Bar{
// ...
}
Bar2 "ActualType" is still Bar, and there is nothing you can do: you won't be able to use ChangeHandlers for Bar2
To avoid the issue, the only possible fix I see is to delegate the cast operation to an other class (you could also use a default method in the ChangeHandler interface).
Here is a possibility:
public class Foo // no more type parameter
{
private final List<FooCaster<?>> casterHandlers = new ArrayList<>();
/**
* unsafe because you could register a ChangerHandler of any type.
* worst of all, everything is unchecked cast so the error could show up late.
*/
public <T> void addChangeHandler(ChangeHandler<T> handler) {
casterHandlers.add(new FooCaster<T>(handler));
}
protected void reportChange() {
for (FooCaster<?> caster: casterHandlers) {
caster.reportChange(this);
}
}
class FooCaster<T> {
protected ChangeHandler<T> ch;
protected FooCaster(ChangeHandler<T> ch) {
this.ch = ch;
}
#SuppressWarnings("unchecked")
public void reportChange(Foo f) {
ch.onChange((T)f);
}
}
}
Personnaly in the case of broadcasting changes to listener/changehandlers, I'm enclined to externalize the process to an other class, which makes it possible to use parameter types properly and avoid unsafe casts.If you are still willing to use reportChange() from within the foo object, here is a possible implementation (otherwise you could store a T reference in the Broadcaster).
public class Broadcaster<T extends Foo> {
protected final List<ChangeHandler<? super T>> changeHandlers;
public Broadcaster() {
this.changeHandlers = new ArrayList<>();
}
public void startListeningTo(T obj) {// only T type objects are accepted
obj.registerBroadcaster(this);
}
public void addChangeHandler(ChangeHandler<? super T> changeHandler) {
changeHandlers.add(changeHandler);
}
void reportChange(Foo obj) {
T o = (T)obj;
for(ChangeHandler<? super T> c : changeHandlers) {
c.onChange(o);
}
}
}
public class Foo {
private final List<Broadcaster<?>> broadcasters = new ArrayList<>();
// cannot be accessed from outside of the package, only Broadcaster.startListeningTo(T o) can be used
final void registerBroadcaster(Broadcaster<?> b) {
broadcasters.add(b);
}
public final void reportChange() {
for (Broadcaster<?> b: broadcasters) {
b.reportChange(this);
}
}
}
public class Bar extends Foo {
// things happen in here that call super.reportChange();
}
public static void test() {
Broadcaster<Bar> broadcaster = new Broadcaster<>();
broadcaster.addChangeHandler(new ChangeHandler<Bar>() {
#Override
public void onChange(Bar obj) {
// do something
}
});
//note that you can use the same broadcaster for multiple objects.
Bar b = new Bar();
broadcaster.startListeningTo(b);
b.reportChange();
}
Note that you will not be able to add changeHandlers from within Bar (but is it really the object's job to register changeHandlers for itself?).
I have the following code
public abstract class Event {
public void fire(Object... args) {
// tell the event handler that if there are free resources it should call
// doEventStuff(args)
}
// this is not correct, but I basically want to be able to define a generic
// return type and be able to pass generic arguments. (T... args) would also
// be ok
public abstract <T, V> V doEventStuff(T args);
}
public class A extends Event {
// This is what I want to do
#Overide
public String doEventStuff(String str) {
if(str == "foo") {
return "bar";
} else {
return "fail";
}
}
}
somewhere() {
EventHandler eh = new EventHandler();
Event a = new A();
eh.add(a);
System.out.println(a.fire("foo")); //output is bar
}
However I don't know how to do this, as I cannot override doEventStuff with something specific.
Does anyone know how to do this?
It's not really clear what you're trying to do, but perhaps you just need to make Event itself generic:
public abstract class Event<T, V>
{
public abstract V doEventStuff(T args);
}
public class A extends Event<String, String>
{
#Override public String doEventStuff(String str)
{
...
}
}
You're using generics but you are not providing a binding.
public abstract class Event<I, O> { // <-- I is input O is Output
public abstract O doEventStuff(I args);
}
public class A extends Event<String, String> { // <-- binding in the impl.
#Override
public String doEventStuff(String str) {
}
}
Or simpler with only one generic binding...
public abstract class Event<T> { // <-- only one provided
public abstract T doEventStuff(T args);
}
public class A extends Event<String> { // <-- binding the impl.
#Override
public String doEventStuff(String str) {
}
}
Let the following code:
public abstract class MySuperClass {
public abstract void update();
/* ... */
}
public class A extends MySuperClass {
#Override
public void update() { /* ... */ }
/* ... */
}
public class B extends MySuperClass {
#Override
public void update() { /* ... */ }
/* ... */
}
public class Ticket<T extends MySuperClass> {
private Class<T> c;
public Ticket(Class<T> c){ this.c = c; }
public Class<T> getClass() { return this.c; }
public void update() { /* HOW TO DO! */ }
/* ... */
}
public class Main {
public static void main(String[] args) {
Ticket<A> myTicket1 = new Ticket<A>(A.class);
Ticket<B> myTicket2 = new Ticket<B>(B.class);
myTicket1.update();
myTicket2.update();
}
}
How do I upgrade the tickets depending on his type (A, B), or so on?
Why does Ticket know anything about what update actually means. It just needs to forward the call to an instance of MySuperClass. The whole point of generic classes is that the generic class will work with any object (or subset of objects) without having to know exactly what kind it is.
public class Ticket<T extends MySuperClass> {
private T thing;
public Ticket(T thing) {
this.thing = thing;
}
public void update() {
thing.update();
}
/* ... */
}
update() is an instance method, so you will need an instance to call it. This can be achieved with
getClass().newInstance().update();
Due to polymorhism, it will call the correct method from A or B.
But to solve it in a more object oriented way, you should pass a instance to the Ticket constructor and just call update().
I've tweaked your example so that it makes more sense ... and implemented update.
public class Ticket<T extends MySuperClass> {
private Class<T> c;
private T t;
public Ticket(Class<T> c) throws InstantiationException, IllegalAccessException {
this.c = c;
this.t = c.newInstance();
}
public Class<T> getClass() {
return this.c;
}
public void update() {
t.update();
}
/* ... */
}
The update method calls t.update() which will polymorphically dispatch to the update method of the actual object that t refers to. Note that I added code to create and store the instance of Class<T>.
UPDATE - I've added the exceptions to the Ticket constructor. This is the part of the price you pay for using reflection to create instances ... rather than creating them using new and passing them as arguments.