when I create an object of the class BinaryTreeNode , I want to pass two String in the Constructor rather than an object of the class BinaryTreeNode how can I do that.
BinaryTreeNode(BinaryTreeNode left,BinaryTreeNode right) {
this.left = left;
this.right = right;
}
BinaryTreeNode b = new BinaryTreeNode("B","A");
Write another constructor that takes two String parameters.
BinaryTreeNode(String left, String right) {
//whose knows why I want to do this...
}
You can't cast a String into a BinaryTreeNode, that would throw an Exception.
It is not possible to cast any object to a type which it is not.
But that is fine, and I suspect it is not the root of the problem, because it doesn't make sense to treat a String object as a BinaryTreeNode - they have naught in common except that which they both inherit from Object.
Thus, I would either make the "node/leaf value" part of the BinaryTreeNode type or, I may introduce a leaf node type such as:
class BinaryTreeLeafNode extends BinaryTreeNode {
public final String value;
public BinaryTreeLeafNode (String value) {
super(null, null); // got anything better? :|
this.value = value;
}
}
Then:
tree = new BinaryTreeNode(
new BinaryTreeLeafNode("Left"),
new BinaryTreeLeafNode("Right"));
And perhaps if I wanted to hide the details, then an overload could be introduced:
public BinaryTreeNode (String leftValue, String rightValue) {
this(new BinaryTreeLeafNode(leftValue), new BinaryTreeLeafNode(rightValue));
}
(I would advise against widening the left/right member and constructor types to to Object, as that will eliminate a good bit of type-safety.)
Related
The following Java code is valid - no compile- or run-time errors.
public class Test {
public static void main(String[] args) {
System.out.println(
new Comparator<>("hello", 5).areEqual()
);
}
private static class Comparator<T> {
private final T left;
private final T right;
public Comparator(T left, T right) {
this.left = left;
this.right = right;
}
public boolean areEqual() {
return left.equals(right);
}
}
}
I expect the values "hello" and 5 are casted to Object, which is a common parent.
Is there a way to write the class in such a way that passing other than objects of the same type causes a compile-time error? I.e. passing objects casted to a common ancestor not allowed.
Not really, no.
Because your generic type is unbound, there's only one common ancestor: Object - as you correctly surmise.
The only thing you can realistically do in this scenario is ensure that equals is correctly defined for objects you want to pass through this method. You would also want to handle cases in which you pass null as an argument, too.
Just specify the type in the generic parameters...
public class Test {
public static void main(String[] args) {
System.out.println(
new Comparator<String>("hello", 1).areEqual()
);
}
...
}
If you do this with your current code, you will get a compiler error.
When you leave it unspecified, Java does not bother doing any type checking and simply uses the super type (Object) as the type for both.
You will also find the same issue when you do something like:
System.out.println(Arrays.asList("hello", 1)); // Will compile
vs
System.out.println(Arrays.<String>asList("hello", 1)); // Will not compile
So, I think it is not possible by using generic. But you can restrict it by checking the Object type in the constructor like below code.
public Comparator(T left, T right) {
if(left.getClass()!=right.getClass()) {
throw new IllegalArgumentException("All values passed needs to be object of same class");
}
this.left = left;
this.right = right;
}
However, this will not give you compile time error but it will through Exception when a different type of object passed to the constructor.
As #Makoto already answered, the short answer is no.
If you look at code snippet for equals method in your favorite IDE then you'll see that it has line like if (getClass() != another.getClass()) return false; It means that you check class of object inside equals. You could do the same at areEqual method but probably it's not needed - it should be implemented on another level
I have this bit of code and it keeps saying that it cannot create a generic array, but, I don't have a generic in my Node class, just an Object field. The Node class is an inner class. Why is it doing this?
public class TernarySearchTrie<E> implements TrieInterface<E> {
private Node[] root = new Node[256];
private int size = 0;
private class Node {
char c;
Node left, mid, right;
Object value;
}
}
Add the static modifier to Node class:
private static class Node {
char c;
Node left, mid, right;
Object value;
}
Without static, it depends of the TernarySearchTrie class, that have generics.
What you do in the problematic new Node[256] is actually TernarySeachTrie<E>.Node[256]. One solution is to use raw type:
Node[] root = TernarySearchTrie.Node[256];
Of course the compiler gives you a warning for this.
I am new to object oriented programming and I am trying to declare and initialize left, but I don't know how to do it. I tried
left = new Counter(4, left.mod);
But it Netbeans is saying that
incompatible types: int cannot be converted to Number
This is not the real program.
public class Number{
private int mod;
public Number(int modulus, Number left) {
mod = modulus;
//how to declare left?
}
It seems like you are trying to implement some sort of linked list etc. Obviously you want left to be remembered, so declare it just like any other normal property of the class.
public class Number{
private Number left;
private int mod;
public Number(int modulus, Number left) {
mod = modulus;
this.left = left;
}
}
If you really need to interact with two classes that have the same name in a class, you'll have to use the fully-qualified name to refer to one or the other. So, if for instance you want to refer to a java.lang.Number inside your own Number class, you'd do
public class Number{
private java.lang.Number left;
private int mod;
public Number(int modulus, java.lang.Number left) {
mod = modulus;
this.left = left;
}
}
(note that my emphasis on really is indicating that, as you can probably already guess, it's generally more trouble than it's worth to give a class the same name as a commonly-used library type).
I'm trying to understand how the code in this Polymorphism exercise works.
I think I understand the concept; however, I'm having trouble understanding how to apply it to the equation: 1 + 2 * 3
abstract class Node {
abstract double evaluate();
}
public class ValueNode extends Node {
double value;
double evaluate() {
return value;
}
}
public abstract class OpNode extends Node {
Node left;
Node right;
abstract double evaluate();
}
public class MultiplicationNode extends OpNode {
double evaluate() {
return left.evaluate() * right.evaluate();
}
}
public class AdditionNode extends OpNode {
double evaluate() {
return left.evaluate() + right.evaluate();
}
}
Note It seems to me that Node would be more appropriately defined as an interface in this context. Are you sure that it's not meant to be an interface instead of an abstract class?
You are attempting to represent the equation
1 + 2 * 3
According to your code, you have two types of Node:
ValueNode - represents a value
OpNode - represents an operation
Therefore, according to your equation, you have 5 nodes:
ValueNode = 1
AdditionNode = +
ValueNode = 2
MultiplicationNode = *
ValueNode = 3
Note that AdditionNode and MultiplicationNode are types of OpNode.
Each OpNode refers to a left Node and a right Node. It's important to understand that either of these Node's can be a ValueNode or an OpNode.
Don't forget order of operations, though. Multiplication comes before Addition.
So, when you represent this relationship as a series of nodes, you need to keep that in mind.
If you had the proper constructors on your code (you don't), you'd do the following with Dependency Injection:
Node node = new AdditionNode(
new ValueNode(1),
new MultiplicationNode(
new ValueNode(2),
new ValueNode(3)
)
);
Now, when you call
node.evaluate();
You will get the answer to the equation.
Your constructors should look like this:
class ValueNode {
double value;
public ValueNode(double value) {
this.value = value;
}
}
class OpNode {
Node left;
Node right;
public OpNode(Node left, Node right) {
this.left = left;
this.right = right;
}
}
Here is a working example: http://ideone.com/oCVR8S
The #Override annotations should be above any methods that are overridden from a subclass' or interface's method.
Is it a design flaw to have a static final variable in a generic class? Consider the class below, all references to Node.SOIL give rise to warnings. What is a good way of going about solving this problem?
public class Node<E> {
private static int nodeCounter = 0;
#SuppressWarnings({ "unchecked", "rawtypes" })
public static final Node SOIL = new Node(null, null); // <-- HERE
public static void resetSOIL(){
SOIL.children = null; // <-- HERE
}
private Node<E> parent;
private Set<Node<E>> children;
protected Set<Node<E>> isomorphs;
private E data;
private int id;
public Node(Node<E> parent, E data){
this.parent = parent;
this.data = data;
this.id = ++nodeCounter;
}
public boolean isRoot(){
return (this.getParent() == SOIL);
}
// utility methods
....
}
You've defined a type Node<E> which represents a node in a tree of E's. For example, Node<Integer> is a node in a tree of Integers, and Node<String> is a node in a tree of Strings.
Now you want a variable SOIL that contains all the roots of these various trees of different types (hehe, soil, I get it now). Set aside the static field issue for now. What should the class of SOIL be? In other words, how do we declare and create the SOIL instance?
Node</*something1*/> SOIL = new Node</*something2*/>(null, null);
Since SOIL is going to have children that are Node<Integer> and Node<String> then it has to be something like Node<?> or Node<Object>. You can't instantiate an object using a wildcard type argument, so the best you can do is something like this:
Node<?> SOIL = new Node<Object>(null, null);
(If you use the Java 7 diamond construct new Node<>(...) it ends up using Object in this case anyway.)
The problem is, this still doesn't work. The way the Node<E> type is defined is as a homogeneous tree of E's. But one subtree of SOIL is a tree of Integers and another subtree is a tree of Strings, so SOIL wants to be a heterogeneous tree. Therefore, SOIL cannot be a Node<E> for any E.
At least, not in a type-safe fashion. You could write the code to do this, but you'd have to add some casts, and you'd get unchecked warnings. These warnings would tell you that this approach isn't working. For example, consider some code that takes a Node<E> and operates on all of its siblings (that is, the other children of its parent). Some code that took a Node<Integer> could call this and end up with a bunch of instances of Node<String> and start throwing ClassCastExceptions.
You might consider making SOIL a Set<Node<?>> and not making it be the parent of all the roots. You could make it a static field somewhere, but make it private.
It's not a design flaw to have a static final variable. The warning appears because you are declaring an instance of a generic type without providing a type parameter:
public static final Node SOIL = new Node(null, null); // <-- HERE
when the compiler is expecting something like:
public static final Node<SomeType> SOIL = new Node<SomeType>(null, null);
You could use this to avoid suppressWarnings and it works well:
private static final Node<Object> SOIL = new Node<Object>(null, null);
To answer to your other question:
Is it a design flaw to have a static final variable in a generic class?
No itsnt, it is even a good common practice to use it as default for null variables of type Node, aka the NULL object in Effective Java Programming