I have a generic Element class which contains elements of the same class. Based on that I would then create concrete classes like
Boxes extends Element<Boxes>
The point I don't get is the
setParent(this);
Why do I need to cast it
setParent((C) this);
(and suppress type casting warnings)? Obviously I am missing something...
How would you change the class to have no casting and no warnings?
I would argue that "this" is a Element object (at minimum) and C as well.
public class Element<C extends Element<C>> {
List<C> children;
C parent = null;
public Element() {
}
void setChildren(List<C> children) {
this.children = children;
for (C c : children) {
c.setParent((C) this); // warning, without the cast: error
}
}
void setParent(C parent) {
this.parent = parent;
}
You get this error because this is of type Element<C> and not of type C.
The following would work:
public class Element<C extends Element<C>> {
List<C> children;
Element<C> parent = null;
public Element() {
}
void setChildren(List<C> children) {
this.children = children;
for (C c : children) {
c.setParent(this);
}
}
void setParent(Element<C> parent) {
this.parent = parent;
}
}
Btw, IDEs are pretty good explaining why you get such errors.
Because nothing guarantees that this is of type C.
For example, you could create an object this way:
Element<Boxes> e = new Element<>();
or this way:
class Container extends Element<Boxes> {}
...
Container c = new Container();
You can add protected abstract C self() method to Element<C> class and use it instead of (C) this:
public abstract class Element<C extends Element<C>> {
List<C> children;
C parent = null;
protected abstract C self();
void setChildren(List<C> children) {
this.children = children;
for (C c : children) {
c.setParent(self());
}
}
void setParent(C parent) {
this.parent = parent;
}
}
Now when you extend Element<C> you can implement self() just by returning this:
public class Boxes extends Element<Boxes> {
#Override
protected Boxes self() {
return this;
}
}
This is a pretty popular design. You can see it, for example, if you delombok builders which are generated with Lombok #SuperBuilder annotation:
public class Example {
private final int someField;
protected Example(ExampleBuilder<?, ?> b) {
this.someField = b.someField;
}
public static ExampleBuilder<?, ?> builder() {
return new ExampleBuilderImpl();
}
public static abstract class ExampleBuilder<C extends Example, B extends ExampleBuilder<C, B>> {
private int someField;
public B someField(int someField) {
this.someField = someField;
return self();
}
protected abstract B self();
public abstract C build();
public String toString() {
return "Example.ExampleBuilder(someField=" + this.someField + ")";
}
}
private static final class ExampleBuilderImpl extends ExampleBuilder<Example, ExampleBuilderImpl> {
protected Example.ExampleBuilderImpl self() {
return this;
}
public Example build() {
return new Example(this);
}
}
}
Related
i have some redundant code that i would like to remove, my goal would be to create a method of this kind:
private GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
Where this method can pass two similar classes but which differ in the type of an attribute
public class Class1{
private Tipe1 tipe1;
private String value;
private String value2;
//Constructor,Getter and Setter
}
public class Class2{
private Tipe2 tipe2;
private String value;
private String value2;
//Constructor,Getter and Setter
}
What I would like to do is call the method
someServiceIml.myMethod ("Foo")
passing either an object of type Class1 or Class2 according to my needs, the business logic behind myMethod is practically the same.
This method i wish it was in the same implementation of a certain service, could you give me some solution?
Create a generic abstract type; either a super class or an interface:
public interface GenericClass<T> {
public T getTipe();
public void setValue(String s);
public void setValue2(String s);
}
Have your implementation classes implement it:
public class Class1 implements GenericClass<Tipe1> {
// leave implementation as is
}
public class Class2 implements GenericClass<Tipe2> {
// leave implementation as is
}
And type your method:
private <T> GenericClass<T> myMethod(GenericClass<T> genericClass){
T tipe = genericClass.getTipe();
genericClass.setValue("foo");
genericClass.setValue2("foo");
// some logic
return genericClass;
}
If Tipe1 and Tipe2 share a common type, you can type them too:
public interface GenericClass<T extends SomeTipe> {
public class MyClass {
public static void main(String args[]) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
GenericClass gc = myMethod(c1);
System.out.println(gc);
}
private static GenericClass myMethod(GenericClass genericClass){
genericClass.getTipe(); //tipe1 or tipe2
genericClass.setValue("foo");
genericClass.setValue2("foo");
//some logic
return genericClass;
}
}
class Class1 extends GenericClass<Tipe1>{
}
class Class2 extends GenericClass<Tipe2>{
}
class Tipe1 {
}
class Tipe2 {
}
class GenericClass<T> implements Tipe<T> {
private String value;
private String value2;
private T t;
public T getTipe() {
return t;
}
void setValue(String s) {
value = s;
}
void setValue2(String s) {
value2 = s;
}
}
interface Tipe<T> {
public T getTipe();
}
or you can cast to parent class like:
GenericClass gc = new Class2();
I want to get rid of the following code duplication within the MyFacadeBean. Consider the following situation:
public class FacadeBean implements Facade {
#EJB
private CrudService crudService;
#Inject
private FirstAssembler firstAssembler;
#Inject
private SecondAssembler secondAssembler;
#Inject
private ThirdAssembler thridAssembler;
#Inject
private FourthAssembler fourthAssembler;
#Override
public void save(FirstValue value) {
FirstEntity entity = this.firstAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
#Override
public void save(SecondValue value) {
SecondEntity entity = this.secondAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
#Override
public void save(ThirdValue value) {
ThirdEntity entity = this.thirdAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
#Override
public void save(FourthValue value) {
FourthEntity entity = this.fourthAssembler.transformToEntity(value);
this.crudService.persist(entity);
}
}
public interface MyFacade {
void save(FirstValue value);
void save(SecondValue value);
}
With the CrudService:
public interface CrudService {
void persist(Object entity);
}
#Stateless
#Local(CrudService.class)
#TransactionAttribute(TransactionAttributeType.MANDATORY)
public class CrudServiceBean implements CrudService {
public static final String PERSISTENCE_UNIT_NAME = "my_persistence_unit";
private EntityManager entityManager;
#PersistenceContext(unitName = PERSISTENCE_UNIT_NAME)
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public void persist(Object entity) {
this.entityManager.persist(entity);
}
}
With the following assemblers:
public class FirstAssembler extends AbstractAssembler<FirstEntity> {
public FirstEntity transformToEntity(FirstValue value) {
if (value == null)
return null;
FirstEntity entity = new FirstEntity();
transformAbstractValueToAbstractObject(value, entity);
entity.setFixedRate(value.getFixedRate());
entity.setStartDate(value.getStartDate());
return entity;
}
}
public class SecondAssembler extends AbstractAssembler<SecondEntity> {
public SecondEntity transformToEntity(SecondValue value) {
if (value == null)
return null;
SecondEntity entity = new SecondEntity();
transformAbstractValueToAbstractObject(value, entity);
entity.setTransactionType(value.getTransactionType());
entity.setValueDate(value.getValueDate());
return entity;
}
}
public abstract class AbstractAssembler<T extends AbstractEntity> {
protected void transformAbstractValueToAbstractObject(AbstractValue value, T object) {
object.setUniqueId(value.getUniqueId());
object.setNominalAmountValue(value.getNominalAmountValue());
}
}
With the following entities:
#Entity
public class FirstEntity extends AbstractEntity {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ID")
private Long id;
#Column(name = "START_DATE")
#Temporal(TemporalType.DATE)
private Date startDate;
#Column(name = "FIXED_RATE")
#Digits(integer = 1, fraction = 10)
private BigDecimal fixedRate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public BigDecimal getFixedRate() {
return fixedRate;
}
public void setFixedRate(BigDecimal fixedRate) {
this.fixedRate = fixedRate;
}
}
#Entity
public class SecondEntity extends AbstractEntity {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "ID")
private Long id;
#Column(name = "VALUE_DATE")
#Temporal(TemporalType.DATE)
private Date valueDate;
#Column(name = "TRANSACTION_TYPE")
#Enumerated(EnumType.STRING)
private TransactionType transactionType;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getValueDate() {
return valueDate;
}
public void setValueDate(Date valueDate) {
this.valueDate = valueDate;
}
public TransactionType getTransactionType() {
return transactionType;
}
public void setTransactionType(TransactionType transactionType) {
this.transactionType = transactionType;
}
}
#MappedSuperclass
public abstract class AbstractEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "TRANSACTION_NOM_AMOUNT_VALUE")
#Digits(integer = 18, fraction = 5)
#Min(0)
private BigDecimal nominalAmountValue;
public BigDecimal getNominalAmountValue() {
return nominalAmountValue;
}
public void setNominalAmountValue(BigDecimal nominalAmountValue) {
this.nominalAmountValue = nominalAmountValue;
}
}
I tried the following approach:
public class FacadeBean implements Facade {
#Inject
private Assembler assembler;
#Inject
private AssemblerFactory assemblerFactory;
#Override
public <T extends AbstractValue> void save(T value) {
Assembler assembler = assemblerFactory.createAssembler(value);
AbstractEntity entity = assembler.transformToEntity(value);
this.crudService.persist(entity);
}
}
Problems are the AssemblerFactoryImpl and the AssemblerImpl in which I have to do instanceOf checks and castings...
Another idea would be to let the value know which transformer to use (or how to transform). But I want the value to be "dumb".
#Glenn Lane
public AbstractValue save(AbstractValue value) {
AbstractAssembler<AbstractValue, AbstractEntity> assembler = new FirstAssembler();
AbstractEntity entity = assembler.transformToEntity(value);
AbstractValue result = assembler.transformToValue(entity);
return result;
}
does not work, because of
Type mismatch: cannot convert from FirstAssembler to AbstractAssembler
I'm posting this as a separate answer, since I don't really think there's anything wrong with having a save method for every AbstractValue type.
First we'll establish your base value class for this example. I'm using an interface just so we don't muddy the waters. Your AbstractValue interface:
public interface AbstractValue
{
int getUniqueId();
double getNominalValue();
<T> T accept(AbstractValueVisitor<T> visitor);
}
And the "visitor interface":
public interface AbstractValueVisitor<T>
{
T visit(FirstValue value);
T visit(SecondValue value);
T visit(ThirdValue value);
T visit(FourthValue value);
}
I know you don't want intelligence baked into AbstractValue, but we are going to add one specification... that all concrete implementations of AbstractValue (all four) implement the accept method exactly this way:
#Override
public <T> T accept(AbstractValueVisitor<T> visitor)
{
return visitor.visit(this);
}
So that method is implemented four times: in all four value classes, exactly the same way. Because the visitor interface is aware of all concrete implementations, the appropriate method will be called for each particular value type. All three of these parts put together is the "visitor pattern".
Now we'll make an entity factory. Its job is to create the appropriate AbstractEntity when provided an AbstractValue:
public class AbstractEntityFactory
implements AbstractValueVisitor<AbstractEntity>
{
private static final AbstractEntityFactory INSTANCE;
static
{
INSTANCE = new AbstractEntityFactory();
}
// Singleton pattern
private AbstractEntityFactory()
{
}
public static AbstractEntity create(AbstractValue value)
{
if (value == null)
{
return null;
}
AbstractEntity e = value.accept(INSTANCE);
e.setNominalValue(value.getNominalValue());
e.setUniqueId(value.getUniqueId());
return e;
}
#Override
public AbstractEntity visit(FirstValue value)
{
FirstEntity entity = new FirstEntity();
// Set all properties specific to FirstEntity
entity.setFixedRate(value.getFixedRate());
entity.setStartDate(value.getStartDate());
return entity;
}
#Override
public AbstractEntity visit(SecondValue value)
{
SecondEntity entity = new SecondEntity();
// Set all properties specific to SecondEntity
entity.setTransactionType(value.getTransactionType());
entity.setValueDate(value.getValueDate());
return entity;
}
#Override
public AbstractEntity visit(ThirdValue value)
{
ThirdEntity entity = new ThirdEntity();
// Set all properties specific to ThirdEntity
return entity;
}
#Override
public AbstractEntity visit(FourthValue value)
{
FourthEntity entity = new FourthEntity();
// Set all properties specific to FourthEntity
return entity;
}
}
Now your facade implementation takes an AbstractValue, and you got that one save method you're looking for:
public class FacadeBean implements Facade
{
#EJB
private CrudService crudService;
#Override
public void save(AbstractValue value)
{
AbstractEntity entity = AbstractEntityFactory.create(value);
crudService.persist(entity);
}
}
Because your AbstractValue now follows the visitor pattern, you can do all sorts of polymorphic behavior. Such as:
public class AbstractValuePrinter implements AbstractValueVisitor<Void>
{
private final Appendable out;
public AbstractValuePrinter(Appendable out)
{
this.out = out;
}
private void print(String s)
{
try
{
out.append(s);
out.append('\n');
}
catch (IOException e)
{
throw new IllegalStateException(e);
}
}
#Override
public Void visit(FirstValue value)
{
print("I'm a FirstValue!");
print("Being a FirstValue is groovy!");
return null;
}
#Override
public Void visit(SecondValue value)
{
print("I'm a SecondValue!");
print("Being a SecondValue is awesome!");
return null;
}
#Override
public Void visit(ThirdValue value)
{
print("I'm a ThirdValue!");
print("Meh.");
return null;
}
#Override
public Void visit(FourthValue value)
{
print("I'm a ThirdValue!");
print("Derp.");
return null;
}
}
In this example, this visitor isn't returning anything... it's "doing" something, so we'll just set the return value as Void, since it's non-instantiatable. Then you print the value simply:
// (value must not be null)
value.accept(new AbstractValuePrinter(System.out));
Finally, the coolest part of the visitor pattern (in my opinion): you add FifthValue. You add the new method to your visitor interface:
T visit(FifthValue value);
And suddenly, you can't compile. You must address the lack of this handling in two places: AbstractEntityFactory and AbstractValuePrinter. Which is great, because you should consider it in those places. Doing class comparisons (with either instanceof or rinde's solution of a class-to-factory map) is likely to "miss" the new value type, and now you have runtime bugs... especially if you're doing 100 different things with these value types.
Anyhoo, I didn't want to get into this, but there you go :)
Use a generic method with a bound type parameter in order to spare yourself the repetition:
public <T extends AbstractValue> T save(T value) {...}
Within the method body, you'll be able to reference the argument value with all methods pertaining to AbstractValue.
Notes
Since your save methods seem to be overrides in this example, you might need to change the design of the parent class or interface too.
You could also use a generic class to start with (instead of a generic method in a non-necessarily generic class), depending on your use case.
I think a problem in your code is that the generic type of AbstractAssembler is that of the output of the transform method, not the input. If you change it as follows:
public abstract class AbstractAssembler<T extends AbstractValue> {
protected void transformAbstractValueToAbstractObject(AbstractEntity entity, T value) {
entity.setUniqueId(value.getUniqueId());
entity.setNominalAmountValue(value.getNominalAmountValue());
}
public abstract AbstractEntity transformToEntity(T value);
}
Then you can change the FacadeBean to the following.
public class FacadeBean {
#EJB
private CrudService crudService;
final Map<Class<?>, AbstractAssembler<?>> knownAssemblers;
FacadeBean() {
knownAssemblers = new LinkedHashMap<>();
knownAssemblers.put(FirstValue.class, new FirstAssembler());
knownAssemblers.put(SecondValue.class, new SecondAssembler());
// add more assemblers here
}
public <T extends AbstractValue> void save(T value, Class<T> type) {
#SuppressWarnings("unchecked") // safe cast
final AbstractAssembler<T> assembler =
(AbstractAssembler<T>) knownAssemblers.get(type);
final AbstractEntity entity = assembler.transformToEntity(value);
this.crudService.persist(entity);
}
}
Notice that I changed the signature of the save(..) method such that we have the type of the object that needs to be saved. With this type we can simply lookup the right assembler that should be used. And because the assembler is now generic on its input type, we can do a safe cast (be careful to keep your map consistent).
This implementation avoids duplication of code as you only need one save method. The use of the instanceof operator is prevented by changing the generic type of AbstractAssembler and storing all assemblers in a map.
The assemblers can look like this:
public class FirstAssembler extends AbstractAssembler<FirstValue> {
#Override
public FirstEntity transformToEntity(FirstValue value) {
final FirstEntity entity = new FirstEntity();
// do transformational stuff
super.transformAbstractValueToAbstractObject(entity, value);
entity.setFixedRate(value.getFixedRate());
entity.setStartDate(value.getStartDate());
return entity;
}
}
public class SecondAssembler extends AbstractAssembler<SecondValue> {
#Override
public SecondEntity transformToEntity(SecondValue value) {
final SecondEntity entity = new SecondEntity();
// do transformational stuff
super.transformAbstractValueToAbstractObject(entity, value);
return entity;
}
}
Note: I'm not familiar with Java beans so you probably have to adapt the code a little if you want to use the #Injected assemblers instead of calling the constructors directly.
You're getting close to gold-plating here, but there is a bit of reduction you can do, specifically the null-check and calling the common field-setting method from each extension.
public abstract class AbstractAssembler<V extends AbstractValue, E extends AbstractEntity>
{
public final E transformToEntity(V value)
{
if (value == null)
{
return null;
}
E entity = createEntity(value);
entity.setUniqueId(value.getUniqueId());
entity.setNominalAmountValue(value.getNominalAmountValue());
return entity;
}
/**
* #return
* Appropriate entity object, with the fields not common to all AbstractEntity
* already set
*/
protected abstract E createEntity(V value);
}
And then the extended assembler:
public class FirstAssembler extends AbstractAssembler<FirstValue, FirstEntity>
{
#Override
protected FirstEntity createEntity(FirstValue value)
{
FirstEntity entity = new FirstEntity();
entity.setFixedRate(value.getFixedRate());
entity.setStartDate(value.getStartDate());
return entity;
}
}
If you really want a single factory class to handle all your values/entities, I would look into the visitor pattern, enhanced with a generic type parameter on the visitor interface (and the entity/value accept methods return a type based on the visiting interface). I won't show an example here simply because I don't think it's warranted in your case.
You can have one save method from the point of view of the classes that save those values, but you still have to implement three individual save methods.
Implement a class with all three save methods. For example:
public class ValuePersister {
#Inject
private Assembler1 assembler1;
#Inject
private Assembler2 assembler2;
#Inject
private Assembler3 assembler3;
public Value1 save(Value1 value1, CrudService crudService) {
Entity1 entity1 = assembler1.transformToObject(value1);
crudService.persist(entity1);
return assembler1.transformToValue(entity1);
}
public Value2 save(Value2 value2, CrudService crudService) {
Entity2 entity2 = assembler2.transformToObject(value2);
crudService.persist(entity2);
return assembler2.transformToValue(entity2);
}
public Value3 save(Value3 value3, CrudService crudService) {
Entity3 entity3 = assembler3.transformToObject(value3);
crudService.persist(entity3);
return assembler3.transformToValue(entity3);
}
}
Add an abstract method to AbstractValue:
public abstract AbstractValue save(ValuePersister valuePersister, CrudService crudService);
Implement that method in each class that extends AbstractValue:
#Override
public AbstractValue save(ValuePersister valuePersister, CrudService crudService) {
return valuePersister.save(this, crudService);
}
Inject ValuePersister and implement your original generic save method:
#Inject
private ValuePersister valuePersister;
#Override
public AbstractValue save(AbstractValue value) {
return value.save(valuePersister, crudService)
}
I have an abstract class and several implementations.
Based on the implementation class, I'd like to execute a method and instantiate the implementation class itself with new constructor.
Of course the following won't work as the class is Abstract, and I cannot change this fact. But how could I pass the "logic" how to create each implementation object to the method prepareList()? Especially regarding design decisions.
abstract class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass {
}
class SecondClass extends AbstractClass {
}
class MyService {
void execute(Data data) {
List<FirstClass> list = prepareList(data, FirstClass.class);
//process list
}
List<AbstractClass> prepareList(Data data, Class<? extends AbstractClass> clazz) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
AbstractClass obj = new AbstractClass(); //does of course not work with abstract class
obj.setId();
obj.setName();
obj.setAge();
collection.add(obj);
}
return collection;
}
}
abstract class Fruit { String name; int weight; }
class Apple extends Fruit {}
class Orange extends Fruit {}
class FruitFactory() {
public Fruit create(Data data) {
if ("apple" == data.getFruitName()) return new Apple();
else if ("orange" == data.getFruitName()) return new Orange();
else throw new UnsupportedOperationException();
}
}
class FruitService {
private FruitFactory factory = new FruitFactory();
void execute(Data data) {
List<Fruit> list = prepareList(data);
}
List<Fruit> prepareList(Data data) {
List<Fruit> fruits = new ArrayList<>();
for (Some value : data) {
Fruit fruit = factory.create(data);
// set fields
fruits.add(fruit);
}
return fruits;
}
}
Okay I have a suggestion why don't you do like
public class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass{
}
class SecondClass extends AbstractClass{
}
class Data{
}
class Myservice{
void execute(Data data) {
List<FirstClass> list = prepareList(data, new FirstClass());//notice change
//process list
}
List<AbstractClass> prepareList(Data data, AbstractClass abstractClassObj) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
/* AbstractClass obj = new AbstractClass();*/ //does of course not work with abstract class
abstractClassObj.setId();
abstractClassObj.setName();
abstractClassObj.setAge();
collection.add(obj);
}
return collection;
}
}
BY this your object creation and logic will also remain at different places. It will also be helpful if in future you have another class extending abstract class
or you can have some factory and pass factory object to your method or service class and get instance in the method you want.
Sorry In a hurry I missed the loop thing with factory try some thing like
public class AbstractClass {
int id;
String name;
int age;
//lots of fields
}
class FirstClass extends AbstractClass{
}
class SecondClass extends AbstractClass{
}
class Factory{
public AbstractClass getInstance( Class<? extends AbstractClass> clazz){
if(clazz.getSimpleName().equals(FirstClass.class.getSimpleName())){
return new FirstClass();
}else {
return new SecondClass();
}
}
}
class Data{
}
class Myservice{
private final Factory factory;
public Myservice(Factory factory){
this.factory = factory;
}
void execute(Data data) {
List<FirstClass> list = prepareList(data, FirstClass.class);//notice change
//process list
}
List<AbstractClass> prepareList(Data data, Class<? extends AbstractClass> clazz) {
List<AbstractClass> collection = new ArrayList<>();
for (Some value in data.getList()) {
AbstractClass obj = factory.getInstance(clazz);
abstractClassObj.setId();
abstractClassObj.setName();
abstractClassObj.setAge();
collection.add(obj);
}
return collection;
}
}
Obviously you can modify example as per needs you can use enum sort of things. This is just basic example
tl;dr
Trying to implement a hierarchal fluent interface such that I can combine nodes child classes while also the class standalone, but getting type parameter is not within its bound errors.
Details
I'm trying to achieve a solution so that I can create something such that I can do something like:
farm
.animal()
.cat()
.meow()
.findsHuman()
.saysHello()
.done()
.done()
.dog()
.bark()
.chacesCar()
.findsHuman()
.saysHello()
.done()
.done()
.done()
.human()
.saysHello()
.done();
while also being able to do:
Human human = new Human()
.saysHello()
I've gotten close using various strategies but haven't been able to gain the flexibility described.
My current attempt uses the following classes:
abstract class Base<T extends Base<T>>{
private T parent;
Base(){
}
Base( T parent ){
this.parent = parent;
}
public T done() throws NullPointerException{
if ( parent != null ){
return (T) parent;
}
throw new NullPointerException();
}
}
class Farm<T extends Base<T>> extends Base{
private Animal<Farm<T>> animal;
private Human<Farm<T>> human;
public Farm(){
super();
this.animal = new Animal( this );
this.human = new Human( this );
}
public Animal<Farm> animal(){
return this.animal;
}
public Human<Farm<T>> human(){
return this.human;
}
}
class Animal <T extends Base<T>> extends Base{
private Cat<Animal<T>> cat;
private Dog<Animal<T>> dog;
public Animal(){
super();
init();
}
public Animal( T parent ){
super( parent );
init();
}
private void init(){
this.cat = new Cat(this);
this.dog = new Dog(this);
}
public Cat<Animal<T>> cat(){
return cat;
}
public Dog<Animal<T>> dog(){
return dog;
}
}
class Human<T extends Base<T>> extends Base{
public Human<T> saysHello(){
System.out.println("human says hi");
return this;
}
}
class Cat <T extends Base<T>> extends Base{
private Human<Cat> human;
public Cat(){
super();
init();
}
public Cat( T parent ){
super( parent );
init();
}
private void init(){
this.human = new Human();
}
public Cat<T> meow(){
System.out.println("cat says meow");
return this;
}
public Human<Cat<T>> findsHuman(){
return this.human;
}
}
class Dog <T extends Base<T>> extends Base{
private Human<Dog> human;
public Dog(){
super();
init();
}
public Dog( T parent ){
super( parent );
init();
}
private void init(){
this.human = new Human();
}
public Dog<T> bark(){
System.out.println("dog says woof");
return this;
}
public Dog<T> chacesCar(){
System.out.println("cat drinks milk");
return this;
}
public Human<Dog<T>> findsHuman(){
return this.human;
}
}
The errors I'm seeing are commonly:
Animal.java:4: type parameter Animal is not within its bound private Cat cat;
Animal.java:5: type parameter Animal is not within its bound private Dog dog;
Applied to all similar references and also pertaining to my example desired case:
cannot find symbol
symbol : method dog()
location: class Base.dog()
I've tried using the following solutions which seemed to tackle similar problems, but to no avail, so any and all support is welcome.
References
Is there a way to refer to the current type with a type variable?
http://vyazelenko.com/2012/03/02/recursive-generics-to-the-rescue/
The code below seems to work fine and doesn't need any #SuppressWarnings. The key concept to grasp is that your T parameter is effectively the class of your object's parent, but T's parent could be anything. So instead of T extends Base<T> you want T extends Base<?>.
The output is:
cat says meow
human says hi
dog says woof
cat drinks milk
human says hi
human says hi
...which I believe is correct, although you might want to change your Dog.chacesCar() method so it doesn't output cat drinks milk! Also it should be chases not chaces.
Hope this helps!
abstract class Base<T extends Base<?>> {
private final T parent;
Base() {
this.parent = null;
}
Base(T parent) {
this.parent = parent;
}
public T done() throws NullPointerException {
if (parent != null) {
return parent;
}
throw new NullPointerException();
}
}
class Farm<T extends Base<?>> extends Base<T> {
private final Animal<Farm<T>> animal;
private final Human<Farm<T>> human;
public Farm() {
super();
this.animal = new Animal<>(this);
this.human = new Human<>(this);
}
public Animal<Farm<T>> animal() {
return this.animal;
}
public Human<Farm<T>> human() {
return this.human;
}
}
class Animal<T extends Base<?>> extends Base<T> {
private Cat<Animal<T>> cat;
private Dog<Animal<T>> dog;
public Animal() {
super();
init();
}
public Animal(T parent) {
super(parent);
init();
}
private void init() {
this.cat = new Cat<>(this);
this.dog = new Dog<>(this);
}
public Cat<Animal<T>> cat() {
return cat;
}
public Dog<Animal<T>> dog() {
return dog;
}
}
class Human<T extends Base<?>> extends Base<T> {
public Human() {
super();
}
public Human(T parent) {
super(parent);
}
public Human<T> saysHello() {
System.out.println("human says hi");
return this;
}
}
class Cat<T extends Base<?>> extends Base<T> {
private Human<Cat<T>> human;
public Cat() {
super();
init();
}
public Cat(T parent) {
super(parent);
init();
}
private void init() {
this.human = new Human<>(this);
}
public Cat<T> meow() {
System.out.println("cat says meow");
return this;
}
public Human<Cat<T>> findsHuman() {
return this.human;
}
}
class Dog<T extends Base<?>> extends Base<T> {
private Human<Dog<T>> human;
public Dog() {
super();
init();
}
public Dog(T parent) {
super(parent);
init();
}
private void init() {
this.human = new Human<>(this);
}
public Dog<T> bark() {
System.out.println("dog says woof");
return this;
}
public Dog<T> chacesCar() {
System.out.println("cat drinks milk");
return this;
}
public Human<Dog<T>> findsHuman() {
return this.human;
}
}
Test code:
public static void main(String[] args) {
Farm<?> farm = new Farm<>();
farm
.animal()
.cat()
.meow()
.findsHuman()
.saysHello()
.done()
.done()
.dog()
.bark()
.chacesCar()
.findsHuman()
.saysHello()
.done()
.done()
.done()
.human()
.saysHello()
.done();
Human human = new Human()
.saysHello();
}
The best thing I came up is the following:
new Animal()
.cat()
.meow()
.findsHuman()
.<Cat>done()
.<Animal>done()
.dog()
.bark()
.findHuman()
.<Dog>done()
.done();
With the following base class:
public abstract class Base<T extends Base<T>>{
private Base<?> backRef;
public Base() {}
public Base(Base<?> backRef) {
this.backRef = backRef;
}
#SuppressWarnings("unchecked")
protected T self() {
return (T)this;
}
#SuppressWarnings("unchecked")
public <U extends Base<U>> U done() {
return (U)backRef;
}
}
If you declare backRef as of Type T then the other classes are not allowed because they are not a subclasses of each other, so you have to specify a different type, but since this type is context dependent (one time its Cat, one time its Dog) I don't see an alternative as to pass a hint.
I found a solution:
new Animal()
.cat()
.meow()
.findsHuman()
.done()
.done()
.dog()
.bark()
.findHuman()
.done()
.done();
public abstract class Base<T extends Base<T,P>, P>{
private P backRef;
public Base() {}
public Base(P backRef) {
this.backRef = backRef;
}
#SuppressWarnings("unchecked")
protected T self() {
return (T)this;
}
public P done() {
return backRef;
}
}
Like someone suggested, we add an additional Type for the parent.
Now the base classes:
public final class Cat extends Base<Cat, Animal>{
public Cat() {}
public Cat(Animal backRef) {
super(backRef);
}
public Cat meow() {
System.out.println("Meeeoooww");
return self();
}
public Human<Cat> findsHuman() {
return new Human<Cat>(this);
}
}
As you can see, Cat clearly specifies which base type it should use. Now for human, which can change the type depending on the context:
public final class Human<P> extends Base<Human<P>, P> {
public Human() {}
public Human(P backRef) {
super(backRef);
}
}
Human specifies an additional generic which the caller (Cat, Dog) specifies in their findHuman() Method.
This is what we did on one our project:
public abstract class Parent<T extends Parent<T>> {
/**
* Get {#code this} casted to its subclass.
*/
#SuppressWarnings("unchecked")
protected final T self() {
return (T) this;
}
public T foo() {
// ... some logic
return self();
}
// ... other parent methods
}
public class Child extends Parent<Child> {
public Child bar() {
// ... some logic
return self();
}
// ... other child methods
}
Allowing child to have its own subclass would be:
public class Child<T extends Child<T>> extends Parent<T> {
public T bar() {
// ... some logic
return self();
}
}
In this line:
class Farm<T extends Base<T>>
The compiler treats the second type parameter as a concrete class. For example, say if you replaced that line with this:
class Farm<T extends Base<Double>>
'Double' is a concrete class. When the compiler scans this, it cannot tell the difference between your T and Double, and such treats them both as concrete class, and not type parameters. The only way to let the compiler know T is a type parameter is this way:
class Farm<T extends Base<T>, T>
I hope this answers (or is at least relevant) to your question.
edit
Post was edited while I was typing, so I guess this answer isn't relevant anymore.
You could also play with interfaces, so that you can fake multiple inheritance. A bit verbose, but there is no hazardous casting, and I find it quite understandable.
Define the available methods:
public interface AnimalIn {
AnimalOut animal();
}
public interface CatIn {
CatOut cat();
}
public interface MeowIn {
CatOut meow();
}
public interface DogIn {
DogOut dog();
}
public interface BarkIn {
DogOut bark();
}
public interface ChacesCarIn {
DogOut chacesCar();
}
public interface FindsHumanIn<T> {
HumanOut<T> findsHuman();
}
public interface HumanIn {
HumanOut<FarmOut> human();
}
public interface SaysHelloIn<T> {
HumanOut<T> saysHello();
}
public interface DoneIn<T> {
T done();
}
You may need to have multiple methods in an interface, but I haven't met this need yet. For example, if you had had to kinds of meows:
public interface MeowIn {
CatOut meowForFood();
CatOut meowForMilk();
CatOut meowForStrokes();
}
Define the output types:
Farm provides Animal or Human:
public interface FarmOut extends AnimalIn, HumanIn {
// no specific methods
}
Animal provides Cat, Dog or Done:
public interface AnimalOut extends CatIn, DogIn, DoneIn<FarmOut> {
// no specific methods
}
Cat provides Meow, FindsHuman or Done:
public interface CatOut extends MeowIn, FindsHumanIn<CatOut>, DoneIn<AnimalOut> {
// no specific methods
}
Dog provides Bark, ChacesCar, FindsHuman or Done:
public interface DogOut extends BarkIn, ChacesCarIn, FindsHumanIn<DogOut>, DoneIn<AnimalOut> {
// no specific methods
}
Human provides SayHello or Done:
public interface HumanOut<T> extends SaysHelloIn<T>, DoneIn<T> {
// no specific methods
}
Simply implement the *Out interfaces:
public class Farm implements FarmOut {
#Override
public AnimalOut animal() {
return new Animal(this);
}
#Override
public HumanOut<FarmOut> human() {
return new Human<FarmOut>(this);
}
}
public class Animal implements AnimalOut {
private FarmOut chain;
public Animal(FarmOut chain) {
this.chain = chain;
}
#Override
public CatOut cat() {
return new Cat(this);
}
#Override
public DogOut dog() {
return new Dog(this);
}
#Override
public FarmOut done() {
return chain;
}
}
public class Dog implements DogOut {
private AnimalOut chain;
public Dog(AnimalOut chain) {
this.chain = chain;
}
#Override
public DogOut bark() {
System.out.println("bark");
return this;
}
#Override
public DogOut chacesCar() {
System.out.println("chaces car");
return this;
}
#Override
public HumanOut<DogOut> findsHuman() {
return new Human<DogOut>(this);
}
#Override
public AnimalOut done() {
return chain;
}
}
public class Cat implements CatOut {
private AnimalOut chain;
public Cat(AnimalOut chain) {
this.chain = chain;
}
#Override
public CatOut meow() {
System.out.println("meow");
return this;
}
#Override
public HumanOut<CatOut> findsHuman() {
return new Human<CatOut>(this);
}
#Override
public AnimalOut done() {
return chain;
}
}
public class Human<T> implements HumanOut<T> {
private T chain;
public Human(T chain) {
this.chain = chain;
}
#Override
public HumanOut<T> saysHello() {
System.out.println("hello");
return this;
}
#Override
public T done() {
return chain;
}
}
Those implementations would work also without the interfaces: remove the implements *Out, the #Overrides, and replace any *Out by * (e.g. AnimalOut by Animal). That said, it's easier to maintain with the interfaces: simply update them and fix your compilation errors. It's also easier to find DSL solutions with interfaces (as you can see), and they are sometimes simply necessary.
Demo:
new Farm()
.animal()
.cat()
.meow()
.findsHuman()
.saysHello()
.done()
.done()
.dog()
.bark()
.chacesCar()
.findsHuman()
.saysHello()
.done()
.done()
.done()
.human()
.saysHello()
.done();
Prints:
meow
hello
bark
chaces car
hello
hello
Your problem is that the method done should return the parent, but the parent is not necessarily a T but is just a Base. And the other problem is that whatever the class is, the done method should always return the same class.
But here is a slight variation of your proposed classes. First for Base declaring its concrete class and its concrete parent :
abstract class Base<T extends Base<T, P>, P>{
private P parent;
Base(){
}
Base( P parent ){
this.parent = parent;
}
public P done() throws NullPointerException{
if ( parent != null ){
return parent;
}
throw new NullPointerException();
}
}
That being done, the derived concrete classes become :
class Farm extends Base<Farm, Object>{
private Animal animal;
private Human human;
public Farm(){
super();
this.animal = new Animal( this );
this.human = new Human( this );
}
public Animal animal(){
return this.animal;
}
public Human human(){
return this.human;
}
}
class Animal extends Base<Animal, Farm>{
private Cat cat;
private Dog dog;
public Animal(){
super();
init();
}
public Animal( Farm parent ){
super( parent );
init();
}
private void init(){
this.cat = new Cat(this);
this.dog = new Dog(this);
}
public Cat cat(){
return cat;
}
public Dog dog(){
return dog;
}
}
class Human extends Base<Human, Farm>{
public Human() {
}
public Human(Farm farm) {
super(farm);
}
public Human saysHello(){
System.out.println("human says hi");
return this;
}
}
class CatOrDog extends Base<Cat, Animal>{
protected Human human;
public CatOrDog(){
super();
init(null);
}
public CatOrDog( Animal parent ){
super( parent );
init(parent);
}
private void init(Animal parent){
Animal parent = done();
Farm farm = (parent == null) ? null : parent.done();
this.human = new Human(farm);
}
public Human findsHuman(){
return this.human;
}
}
class Cat extends CatOrDog{
public Cat(){
super();
}
public Cat( Animal parent ){
super( parent );
}
public Cat meow(){
System.out.println("cat says meow");
return this;
}
}
class Dog extends CatOrDog {
public Dog(){
super();
}
public Dog( Animal parent ){
super( parent );
}
public Dog bark(){
System.out.println("dog says woof");
return this;
}
public Dog chacesCar(){
System.out.println("cat drinks milk");
return this;
}
}
With that, I could write without any error or warning :
Farm farm = new Farm();
farm.animal()
.cat()
.meow()
.findsHuman()
.saysHello()
.done()
.animal()
.dog()
.bark()
.chacesCar()
.findsHuman()
.saysHello()
.done()
.animal()
.done()
.human()
.saysHello()
.done();
But note that I had to replace to done calls with animals calls.
Edit :
I added a new class CatOrDog to factorize the Human processing. As the parent of a Human is a Farm, I initialize the new human with a correct parent if it exists. That way, not only the above sources compiles without error or warning, but it also runs without any problem and it prints :
cat says meow
human says hi
dog says woof
cat drinks milk
human says hi
human says hi
There is no "safe" way to do this, but this should compile:
class Dog extends Base{
<T extends Dog> T bark(){
return (T) this;
}
}
I'm trying to access an object inside a managed bean, which implements AbstractMB. Any property accessed by a page has error "Unknown property". When I try to insert it in the database,through a commandButton, PropertyNotFoundException is thrown.
AbstractMB relevant code:
public abstract class AbstractMB<T> implements Serializable {
private Class<T> type;
private AbstractDAO<T> typeDAO;
private T current;
private List<T> elements = new ArrayList();
protected T object = this.getCurrent();
protected List<T> list = this.getElements();
public abstract void save(ActionEvent actionEvent);
public AbstractMB() {}
public AbstractMB(Class<T> type) {
super();
this.type = type;
}
public T getCurrent() {
return current;
}
public void setCurrent(T current) {
this.current = current;
}
}
Full FonteMB class:
#Named
#RequestScoped
public class FonteMB extends AbstractMB<Fonte> {
public FonteMB() {
super(Fonte.class);
}
#Override
public void save(ActionEvent actionEvent) {
if(this.object.getCodigo() == null) {
this.getTypeDAO().add(this.object);
} else {
this.getTypeDAO().edit(this.object);
}
this.object = new Fonte();
this.list = null;
}
}
Class Fonte from the model package implements java.io.Serializable, all getter and setter, hashCode and equals methods. And toString returning the class name ("Fonte").
Also tried to use a converter, but result was the same.
What I'm missing?