I have following class:
class TreeItem<T extends TreeItem<?>>{
private final ObservableList<T> childs;
private T parent;
public void addChild(T unit){
childs.add(unit);
unit.setParent(this);
}
public <T> void setParent(T parent){
this.parent = parent;
}
}
I get this message on setParent:
Incompatible types.
Required: T
Found: T
How can i fix this?
Rewrite this:
public <T> void setParent(T parent){
this.parent = parent;
}
With this:
public void setParent(T parent){
this.parent = parent;
}
Also I would suggest to remove the wildcare in the class name declaration, as the code would not compile.
So replace this:
class TreeItem<T extends TreeItem<?>>
With this:
class TreeItem<T extends TreeItem>
You have a final variable in your class. So it should be initialized either in constructor or inline. As long as you use generic variable and generic type is resolved when you instantiate a new object, the right way to do is to initialize it in constructor like this:
public TreeItem(ObservableList<T> childs) {
this.childs = childs;
}
When you are done with the above proposed changes you may notice that the compiler warns you with the message: Unchecked call to 'setParent(T)'. That means that the compiler does not guarantee the code is safe during runtime and possible heap pollution may occure.
I will illustrate it with an example. The following code while running ends up with ClassCastException as we set parent variable with the type which is not T (it is possible due to type erasure).
class ChildTreeItem<T extends TreeItem> extends TreeItem<T> {
public ChildTreeItem(ObservableList childs) {
super(childs);
}
}
public class TreeItem<T extends TreeItem>{
private final ObservableList<T> childs;
private T parent;
public TreeItem(ObservableList<T> childs) {
this.childs = childs;
}
public void addChild(T unit){
childs.add(unit);
unit.setParent(this);
}
public void setParent(T parent){
this.parent = parent;
}
public T getParent() {
return parent;
}
public static void main(String[] args) {
ChildTreeItem<ChildTreeItem> treeItem =
new ChildTreeItem<>(new ObservableSequentialListWrapper<>(new ArrayList<>()));
TreeItem<ChildTreeItem> parentItem =
new TreeItem<>(new ObservableSequentialListWrapper<>(new ArrayList<>()));
parentItem.addChild(treeItem);
List<ChildTreeItem> itemList = new ArrayList<>();
itemList.add(treeItem.getParent()); //<------------------- Heap pollution
ChildTreeItem childTreeItem = itemList.get(0); //<-------- ClassCastException
}
}
The possible solution to this problem is to not parametrize the variable parent but to make it TreeItem type:
public class TreeItem<T extends TreeItem>{
private final ObservableList<T> childs;
private TreeItem parent;
public TreeItem(ObservableList<T> childs) {
this.childs = childs;
}
public void addChild(T unit){
childs.add(unit);
unit.setParent(this);
}
public void setParent(TreeItem parent){
this.parent = parent;
}
public TreeItem getParent() {
return parent;
}
}
Hope this helps.
Since you have define already in your class level of Generic type. It is not clear why you put before your setParent function. But let's assume you want to define a generic type in function level, then when you call it, you need to specify the type
Ex:
TreeItem<String> treeItem = new TreeItem<String>();
treeItem.<String>setParent("something");
Related
I have a class with a method which returns a list of objects of that class:
public class Parent {
public static List<Parent> all_possible(int i) {
//...
}
//other methods
}
I'm trying to make a Child class that also has this method, except it returns a list of the Child class.
With the code above, I have to rewrite it for the child class because the types are wrong:
public class Child extends Parent {
public static List<Child> all_possible(int i) {
//same thing as above except different type
}
//child methods
}
Is it possible to write this in a way so all the children who inherit from this class use the right type?
Or is there a better way to do this?
Also, is it possible to have variables that change type similarly? For instance:
public class Parent {
public static List<Parent> objects;
}
//...
public class Child extends Parent {
public static List<Child> objects;
}
Thanks in advance.
Edit:
This stackoverflow post explains how to do it with instance methods, but it doesn't explain how to do it with static methods or static variables.
Apparently that is impossible, so what is the alternative I should use?
As described before, static methods cannot be overridden, but the subclass implementation hides the superclass implementation, that is, child's static method is called only when called from reference to Child class.
Example code:
static class Parent {
static List<Parent> objects = new ArrayList<>();
final String name;
public Parent(String name) {
this.name = name;
Parent.objects.add(this);
}
#Override
public String toString() {
return name;
}
static List<? extends Parent> all() {
return new ArrayList<>(Parent.objects);
}
public List<? extends Parent> allPossible(int i) {
return new ArrayList<>(Arrays.asList(new Parent("instance.parent.1"), new Parent("instance.parent.2")));
}
}
static class Child extends Parent {
static List<Child> objects = new ArrayList<>();
static List<Child> all() {
return new ArrayList<>(Child.objects);
}
public Child(String name) {
super(name);
Child.objects.add(this);
}
#Override
public List<Child> allPossible(int i) {
return new ArrayList<>(Arrays.asList(new Child("instance.child.1")));
}
}
Test:
System.out.println("instance");
Parent p = new Parent("main.p");
Parent c = new Child("main.c"); // Child instance referenced by Parent variable
System.out.println(p.allPossible(2));
System.out.println(c.allPossible(2));
System.out.println("static");
System.out.println("p.all: " + p.all());
System.out.println("c.all: " + c.all());
System.out.println("Child.all: " + Child.all());
System.out.println("\nobjects");
System.out.println("p.objects: " + p.objects);
System.out.println("c.objects: " + c.objects);
System.out.println("Child.objects: " + Child.objects);
Output:
instance
[instance.parent.1, instance.parent.2]
[instance.child.1]
static
p.all: [main.p, main.c, instance.parent.1, instance.parent.2, instance.child.1]
c.all: [main.p, main.c, instance.parent.1, instance.parent.2, instance.child.1]
Child.all: [main.c, instance.child.1]
objects
p.objects: [main.p, main.c, instance.parent.1, instance.parent.2, instance.child.1]
c.objects: [main.p, main.c, instance.parent.1, instance.parent.2, instance.child.1]
Child.objects: [main.c, instance.child.1]
After doing some testing, I made a semi-solution.
I turned the static variable objects into a HashMap<Type, ArrayList<Parent>>
Then when I get a list of all the objects, I access the objects with the type of the Child.
Code:
class Parent {
private static Map<Type, List<Parent>> objects = new HashMap<>();
public static List<Parent> all(Class c) {
//...
return objects.get(c);
}
public static List<Parent> all() {
return all(Parent.class);
}
//...
}
class Child {
public static List<Child> getAll() {
return (List<Child>)(List<?>)getAll(Child.class);
}
//...
}
Not a perfect solution, as I still have to write a bit of code in every child class, but it's the best I could find.
I have a Node class:
public class Node<T extends MySuperClass> {
private T data;
private Node<? extends MySuperClass> parent;
private List<Node<? extends MySuperClass>> children;
public Node(T data, Node<? extends MySuperClass> parent, List<Node<? extends MySuperClass>> children) {
this.data = data;
this.parent = parent;
this.children = children;
}
public T getData() {
return data;
}
public Node<? extends MySuperClass> getParent() {
return parent;
}
public List<Node<? extends MySuperClass>> getChildren() {
return children;
}
public void setData(T data) {
this.data = data;
}
public void setParent(Node<? extends MySuperClass> parent) {
this.parent = parent;
}
public void setChildren(List<Node<? extends MySuperClass>> children) {
this.children = children;
}
}
I need to create a map of Generic Node defined above. I have to write something like this
List<Map<Long, Node<? extends MySuperClass>>> tree = new ArrayList<Map<Long, Node< extends MySuperClass>>>();
When I try to add an instance of map to the list
public MyClass extends MySuperClass{
}
Map<Long, Node<MyClass>> myMap = new HashMap<Long,Node<MyClass>>();
tree.add(myMap);
The Compiler gives me the following message:
The method add(Map<Long,Node<? extends MySuperClass>>) in the type List<Map<Long,Node<? extends MySuperClass>>> is not applicable for the arguments (Map<Long,Node<MyClass>>)
Syntactically it is correct. I Can't understand why it doesn't work.
Your Map should be defined the same type as your List.
This is because the List expects a type of Map<Long, Node<? extends MySuperClass>>. The type Node<? extends MySuperClass> and Node<MyClass> are not the same.
From http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html
Note: Given two concrete types A and B (for example, Number and
Integer), MyClass<A> has no relationship to MyClass<B>, regardless of
whether or not A and B are related. The common parent of MyClass<A>
and MyClass<B> is Object.
Note : I add to add a default constructor to your Node class to get the next four lines to compile since I didnt want to type in the params for the other constructor.
List<Map<Long, Node<? extends MySuperClass>>> tree = new ArrayList<Map<Long, Node<? extends MySuperClass>>>();
Map<Long, Node<? extends MySuperClass>> myMap = new HashMap<Long, Node<? extends MySuperClass>>();
myMap.put(1L, new Node<MyClass>());
tree.add(myMap);
I have an abstract generic class which requires a numeric constant to initialize an array. I know the size of array at compile time when I use that generic class. Is there any way to implement this?
abstract class Node<T, MagicN> {
private T parent = null;
private T[] child = (T[]) new Object[MagicN];
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNodeType, 2> {
}
The class ConcreteNode has 2 children in this example.
You can't use a Generic as a template. As Java's code optimisation is done at runtime, there is little reason to have such compile time inlining.
abstract class Node<T extends Node> {
private final T parent;
private final T[] child;
Node(T parent, int size) {
this.parent = parent;
child = (T[]) new Object[size];
}
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNode> {
ConcreteNode(ConcreteNode parent) {
super(parent, 2);
}
}
You can't have values instead of a generic type (or you should have to create a class for each value you may use...)
I think the best in your case would to have a constructor that takes this value as a parameter for example :
abstract class Node<T> {
private T parent = null;
private int MagicN = 0;
private T[] child = null;
protected Node(int MagicN)
{
this.MagicN = MagicN;
this.child = (T[]) new Object[MagicN];
}
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNodeType> {
public ConcreteNode()
{
super(2);
}
}
In terms of performance, there is no difference between what you are trying to do and this example since your child array is initialized in an object context and not a static one.
Why not do it this way?
abstract class Node<T> {
private T parent = null;
private T[] child;
public Node(int childCount) {
child = (T[]) new Object[childCount];
//some methods that rely on the initialized array.
}
final class ConcreteNode extends Node<ConcreteNodeType> {
public ConcreteNode()
{
super(2);
}
}
So I have an AbstractSyntaxTreeNode.java class (here is part of it)
public abstract class ASTreeNode implements Iterable<ASTreeNode>{
protected List<ASTreeNode> children;
protected ASTreeNode(){
children = new LinkedList<ASTreeNode>();
}
protected ASTreeNode(ASTreeNode... children){
this();
for(ASTreeNode c: children)
{
this.addChild(c);
}
And then I have another class Operation that extends ASTreeNode
public class Operation extends ASTreeNode
{
char s;
private Operation(Term t)
{
//QUESTION REGARDING THIS PART
super(t, t.getChild(0), t.getChild(1));
}
}
How do I throw in all of object t's (which also extends ASTreeNode) children into the super ctor arguments? Without hardcoding it like that? I tried super(t, t.children) but the constructor does not take a List in the argument, only ASTreeNodes
are taken.
Oh and this is class term
public class Term extends ASTreeNode
{
char symbol;
private Term(Factor f)
{
super(f, f.getChild(0));
}
}
And theres a bunch more classes that send up their children into another node
Add a constructor in ASTreeNode that accept's a List as it's argument.
public abstract class ASTreeNode ... {
public ASTreeNode(List<? extends ASTreeNode> children) {
this.children = children;
}
}
public class Operation extends ASTreeNode {
char s;
private Operation(Term t) {
super(t.getChildren());
this.addChild(t);
}
}
I'm trying to display a tree of Categories, following the basic CellTree gwt examples.
What I am stuck at is determining the "leaf" condition of a Category.
A Category "is-a-leaf" when it hasn't children, right? So, here's my Category (I am using Objectify for appengine persistence):
#Entity
public class Categoria implements Serializable {
private static final long serialVersionUID = 1L;
#Id
Long id;
String nome;
Key<Categoria> parent;
public Categoria() { }
public Categoria(String nome) {
super();
this.nome = nome;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Key<Categoria> getParent() {
return parent;
}
public void setParent(Key<Categoria> parent) {
this.parent = parent;
}
}
My TreeViewModel is based on AsyncDataProvider (which I pass from outside):
public class CategorieTreeViewModel implements TreeViewModel {
private AbstractDataProvider<Categoria> dataProvider;
public CategorieTreeViewModel(AbstractDataProvider<Categoria> dataProvider) {
this.dataProvider = dataProvider;
}
#Override
public <T> NodeInfo<?> getNodeInfo(T value) {
return new DefaultNodeInfo<Categoria>(dataProvider, new CategoriaCell());
}
#Override
public boolean isLeaf(Object value) {
return false;
}
}
So here it is:
dataProvider = new AsyncDataProvider<Categoria>() {
#Override
protected void onRangeChanged(HasData<Categoria> display) {
updateTree();
}
};
private void updateTree() {
rpcService.getCategorie(new AsyncCallback<Categoria[]>() {
#Override
public void onSuccess(Categoria[] result) {
dataProvider.updateRowCount(result.length, true);
dataProvider.updateRowData(0, Arrays.asList(result));
}
#Override
public void onFailure(Throwable caught) {
Window.alert(caught.toString());
}
});
}
The question is: since I don't have a "leaf property" on my Category bean, how can I know if it has children or not? By doing a query obviously, but the isLeaf method needs to return synchronously, how can I make my rpc call?
Or I can retrieve that "leaf" information in the getCategorie() call, filling the property at runtime, but this could be a performance problem.
What can I do?
I would add a transient property to the Categoria class, a boolean isLeaf, then inside the setParent method, you could set the parent's isLeaf property to false (because if this object has a parent of that, then that object is not a leaf). Making the property transient means it won't be persisted, so you don't have to worry about having that field in your data model.
EDIT: Here is how I would code the Categoria class's setParent method...
public void setParent(Key<Categoria> parent) {
this.parent = parent;
parent.setIsLeaf(false);
}
That way, once you have built up your model of Categoria nodes, each one of them knows whether it is a leaf or not. This works because if parent has this as a child, parent can't possibly be a leaf. Default the isLeaf property to true and you'll know if any given Categoria is a leaf just by checking it's property.