One constructor with one argument that creates two different objects - java

So I'm taking a Java class, and one of the assignments we were given involves abstract data types (ADTs). In this assignment, we're supposed to implement an ADT known as Stack through a class called LinkedStack. LinkedStack has one constructor, but in the test cases my professor provided us, a new LinkedStack object can create either a new LinkedList object or a new ArrayList object. My issue with this is that no matter how I define my argument, I still get an error saying that the argument is incompatible with the classes.
I've tried a logical test to see whether the argument was called as a LinkedList or an ArrayList, which I think is a good thing, but I can't figure out how to properly assign the argument.
I've tried setting the argument to a Stack and then casting to a LinkedStack, with a private final variable being of of type "Stack", I've also tried calling the argument as a List, but I can't seem to get rid of the errors preventing me from starting the compiling process.
This is what we start out with:
interface Stack {
public void push(Object d){
}
public Object pop(){
}
public Object peek(){
}
public boolean isEmpty(){
}
}
public class ListStack implements Stack{
public ListStack(/*argument*/){
}
}
//Separate test case file
//example of the test cases
public void peekTest1() {
Stack q = new ListStack(new LinkedList());
// assertion cases follow
}
public void peekTest2() {
Stack q = new ListStack(new ArrayList());
// assertion cases follow
}

If you look for a type that you can use for /*argument*/, you can do it like this:
public class ListStack implements Stack {
public ListStack(List list) {
}
/* note that you must implement all methods from the interface */
}
Why use type List? List is the common interface, implemented by LinkedList and ArrayList. So you can use one of them in the constructor.
Note: You should not use raw types. List and the classes that implement this interface have a type parameter. When possible you should rather use something like List<String> or List<T>. But maybe, you will learn this in a later lesson.

Related

How to extract information from Java stack as individual data types and use in method call

I am trying to implement an undo feature by creating a stack of 2 subtypes.
I have a stack of parent type UserEntry holding two child types Assign and RelEntry.
Assign and RelEntry is both classes used to insert values (number and relationship) into a grid table.
There is a method call to insert the values into the table as their respective subtypes for example assignToTable() and RelEntryToTable().
I am trying to use a polymorphic method that can call both of these subtypes from the parent stack eg.
parentStack.assignAndRelEntryToTable();
When making the abstract class for UserEntry I have tried an addToPuzzle() method which I then implemented in both child classes however when trying to call using
for (UserEntry ue : stack){
puzzle.addToPuzzle(ue)
}
The method call requires a method specific to each sub-class. I've tried creating a method call for each subclass but the puzzle itself cannot be referenced from the sub-classes.
There are 4 classes working together here: UI, RelEntry, UserEntry, and Assign.
I am trying to create them for each loop within the UI class as this contains the puzzle variable.
If I understand your question correctly, you're looking for instanceof. It let's you check if an object is of given type. Using it you can determine subtype of the UserEntry, cast to desired subtype and call one of your methods accordingly. Something like so:
for (UserEntry ue : stack){
if(ue instanceof Assign){
Assign assign = (Assign) ue;
puzzle.assignToTable(assign );
} else if(ue instanceof RelEntry){
RelEntry relEntry = (RelEntry) ue;
puzzle.relEntryToTable(relEntry);
}
}
I have a hard time understanding your requirements exactly so I am going to be very generic.
Syntax might not be 100% correct but it should give the general idea.
public abstract class UserEntry{
abstract void somCommonMethod();
}
public class RelEntry extends UserEntry{
void someCommonMethod(){
//ownRelEntryLogic
}
}
public class Assign extends UserEntry{
void someCommonMethod(){
//ownAssignLogic
}
}
public Puzzle{
ArrayDeque<UserEntry> stack = new ArrayDeque<>();
public void undoLogic(){
stack.pop().someCommonMethod();
}
public void add(UserEntry anyInstanceOfUserEntry){
stack.push(anyInstanceOfUserEntry);
}
}
}
public class UI{
Puzzle p = new Puzzle();
p.add(new RelEntry());
p.add(new Assign());
}

Is it possible to define a method that accepts any number of nested lists?

I have no particular use for this in mind, but is it possible to write a method that accepts any number of nested lists in Java?
I got as far as this:
private <T extends List<? extends T>> void masterOfLists(final T list) {
}
The small issue with this now is that it never ends. I neither want to lose generics, so simply accepting an Object and try casting it to a List every pass is not an option in my question.
I hoped it would be clear enough, but appereantly it isn't for some, I want the method masterOfLists to accept the following examples (and way more):
masterOfLists(new ArrayList<Object>())
masterOfLists(new ArrayList<List<Object>>())
masterOfLists(new ArrayList<List<List<Object>>>())
masterOfLists(new ArrayList<List<List<List<Object>>>>())
Instead of Object it may also be a concrete type like String.
The used List may be any type of list, like ArrayList or LinkedList or your custom implementation.
Using pure List won't help you here, you need to define a recursive class.
As an additional source of inspiration you can take a look at my code for Recursive Tic-Tac-Toe
You could create a class something like this:
public class Recursive<T> {
List<Recursive<T>> sub;
T value;
boolean hasSub() {
return sub != null;
}
T getValue() {
return value;
}
void forEach(Consumer<T> t) {
if (hasSub())
sub.forEach(t);
else t.accept(value);
}
}
You can use logic in this class to prevent it from both having a sub-list and an actual value, using constructors and/or setters.
And then if you want to iterate over it and print out all the sub-items recursively, you can use
Recursive<T> recursive;
recursive.forEach(System.out::println);
Then your method can look like this:
private <T> void masterOfLists(final Recursive<T> list) {
You won't get anywhere using pure Lists because the generic type of the list is not available at runtime, and the generics will only create a mess for you here. Using a recursive class is much easier.
The 'cheap' solution is to extend the ArrayList class with your own name, and force the Generics on the subclass. The SubClass is still an ArrayList....:
public class NestingList extends ArrayList<NestingList> {
// all we do is set the Generics...
}

Instantiating List<T> with generic type possible?

A student that I am tutoring is taking a web development class that uses a Dietel book on Java, which contains this curious bit of code involving Generics:
class StackComposition <T>
{
private List<T> stackList;
public StackComposition()
{
stackList = new List<T>("stack") // ERROR
}
// .... more code
}
It is apparent to me why this code doesn't work, and I am puzzled as to why the instructor recommends the student use this code as a starting point. Maybe I am just not understanding Generics and my Java skills are deficient, but I don't see how one could instantiate a generic collection with a generic type. I see the intent is to create a Stack by using a generic List collection and determining the type at runtime, but I don't see how this is possible using the above configuration. My first inclination was to tell the student to use the Generic Stack<T> object and forget writing this custom Stack class, but apparently that isn't the goal of the assignment.
I tried as a test using the java.lang.reflect package to work around this, but as far as I can tell this only works with non-generic containers, such as Array:
public StackComposition(Class<T> type)
{
Object obj = Array.newInstance(type, 10);
}
There are two problems in your code:
You're trying to instantiate an interface with new keyword which is illegal. You should be instantiating an object of ArrayList (or a class which implements List) instead.
Second, you're not allowed to pass a String reference to the constructor.
So, here is what you should be using in your code:
stackList = new ArrayList<T>();
or stackList = new ArrayList<T>(10); if you want to give an initial size to your stackList (replace 10 with the size you want your list to be initialized with).
From a purely instructional point of view, the exercise may have been meant to illustrate composition by forwarding certain methods to a contained instance of some more general type. Only the desired methods need be exposed, and the concrete type used internally can be changed as needed.
import java.util.Deque;
import java.util.LinkedList;
public class MyStack<T> {
private Deque<T> deque = new LinkedList<T>();
public void push(T item){
deque.push(item);
}
public T pop() {
return deque.pop();
}
public static void main(String[] args) {
MyStack<Integer> stack = new MyStack<>();
stack.push(42); // OK
stack.addFirst(0); // no such method
}
}

Java Generics (simple case, clear enigma for infering)

I have this class, just for the purpose of learning:
public class MyClass{ //Looking for a solution without making my class also generic <Type>
//Private Arraylist var to hold the value called myvar
public MyClass(ArrayList<MyDesiredType> incoming) {
//CODE myVar=incoming
}
public MyDesiredType getType() {
return myVar.get(0);
}
}
Is there any way to infer in the incoming object from the constructor to the return type of the method without warnings and castings and loosing typesafeness, but most of all WITHOUT making the whole class GENERIC (seems redundant to me)? If not, why should I think this is not feasible for the compiler?
This is a reformulated question I already did, but it was my first one and I learned how to expose it clear because nobody understood. I tried to edit later the original question but everything was buried. I changed and simplified the example and try to put it easy. Original question: Java Generics Silly Thing (Why cant I infer the type?).
If there is any problem just tell it to me and I will remove it.
No, there is not. How would the compiler know what type to return? The generic type of ArrayList in the constructor will not be known during compile time. You either have to make the whole class generic or take another approach.
Consider this:
public class Test {
public static void main(String[] args) {
List<String> arrList = new ArrayList<String>();
arrList.add("FOO");
Test test = new Test(arrList);
String testStr = test.returnWhat();
System.out.println("testStr");
}
private final List myList; //warning
public <T> Test(List<T> ttype) {
myList = ttype;
}
public <T> T returnWhat() {
return (T) myList.get(0); //warning
}
}
This works but gives you warnings on the marked lines. So, really there is no way to achieve what you are describing without making the whole class generic.
Because, what if:
public class Test {
public static void main(String[] args) {
List<String> arrList = new ArrayList<String>();
arrList.add("FOO");
Test test = new Test(); // now what?
String testStr = test.returnWhat(0); // no warning...
JPanel p = test.returnWhat(0); // goes through without warning, real nice...
test.returnWhat(0); // returns Object
Test test2 = new Test(arrList);
test2.addElement(new Object()); // boom, inserted object into list of string.
String nono = test2.returnWhat(1); // the universe goes down. assign an object to string without warning. even
// though one COULD think the class is generic.
}
// private List<T> myList = new ArrayList<T>(); compiler error, T is unknown
private List myList = new ArrayList();
public Test() {
myList.add(new Object());
}
public <T> Test(List<T> ttype) {
myList = ttype;
}
public <T> T returnWhat(int index) {
return (T) myList.get(index);
}
public <T> void addElement(T el) {
myList.add(el);
}
}
The second one doesn't compile when myList is made generic. How could the compiler determine the type of <T> in the case where the default constructor is used?
Further, this could lead to serious problems with Objects in collections that rely on the fact that only certain types are inserted.
This will generate the following exception:
Exception in thread "main" java.lang.ClassCastException:
java.lang.Object cannot be cast to java.lang.String at
Test.main(Test.java:27)
Did I manage to convince you?
Real nice question, btw. I had to think about this one quite a bit.
When you say that you want the compiler to "infer in the incoming object from the constructor to the return type of the method without warnings and castings and loosing typesafeness", it seems that you are saying that it should infer the result of getType() from the input of the constructor. If both happen in the same function, it could. The problem is that the object may not exist in only one function, and so the extra type information (the generic type) is needed to pass this kind of object between functions.
For example, if I want to write a function that takes a MyClass object, I need to know what getType() will return so I can use the returned value. By adding a generic type of MyClass we are giving a description to what it holds.
Another way to look at it is that MyClass is a container. By adding generics, we are saying it is a container of a specific type of thing, and so we can more easily predict what we will get out of it.
There is no way for the compiler to know at runtime what type your arraylist is. I really dont see the problem using something along the lines of this:
public class MyClass<TYPE> {
private ArrayList<TYPE> incoming;
public MyClass(ArrayList<TYPE> incoming) {
this.incoming = incoming;
}
public TYPE getType() {
return incoming.get(0);
}
}
This way you can do:
ArrayList<Integer> numbers = createListOfNumbers();
MyClass<Integer> myClass = new MyClass<>(numbers);
Integer number = myClass.getType();
Or am i misinterpreting the question and you want to know the class at runtime?
No, if you want a class that can hold a list of a parameterized type.
Yes, if you want a class that can hold a list of exactly one type. You can declare that type explicitly in the field, constructor and accessor.
What you're forgetting is that not all code that you may run against is visible to the compiler! Jars can be added, removed, substituted at run time, that the compiler never saw. You may compile against an interface that is just:
public interface MyClassFactory {
MyClass getInstance();
}
Then at runtime you supply into the JVM an implementation. So the compiler never saw the actual code creating the MyClass that you will be using, so there is no way to perform such a compile time inference. You must either make the class generic or accept that there will not be type safety.

When to create a generic class

I haven't used generics before and I am wondering when I should use them and what the advantages are. I think it might be appropriate for a collection that I made since java always uses generics for collections as well but if I call the methods I created the type is already set in the function so it would give an error anyway. When should I use a generic class? Could you give an example because I am not sure how to use it. At the moment my code is as follows:
public class NodeList {
private static final int MAX_AMOUNT_OF_NODES = 12;
private HashMap<String, Node> nodeList;
public NodeList(){
nodeList = new HashMap<String, Node>(MAX_AMOUNT_OF_NODES);
}
public Node get(String id){
return nodeList.get(id);
}
public boolean add(Node node){
if(nodeList.size() <= MAX_AMOUNT_OF_NODES){
nodeList.put(node.id, node);
return true;
}
return false;
}
}
You can look at the existing API for guidance. For example, all the Collections are generic. That is because all collections contain elements of a type.
From that, it makes sense that generic classes should be used when you would have to create the exact same code again and again for different types. If you have to do that, generics might offer you some benefit.
As far as an example, the docs are a good place to start.
From that link, the first code sample is
public class Box<T> {
// T stands for "Type"
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
Conceptually, there is a Box class that is going to contain something. What it contains does not matter, because the type is specific by the programmer. A Box instance can contain basically anything. When the programmer needs to create a box, he/she specifies the type.
Box<SomeClass> myBox = new Box<SomeClass>();
Think about it this way -- if you wanted to create a general Box that could hold anything without generics, you would have to
1) have the field f be an Object, or
2) create a Box class for every type a box could contain.
With generics, you only need one class, and you can specify the exact type. Maybe if you are doing something and your approach involved either 1 or 2 above, it's better to use generics.
If Node is a class that can hold a piece of data with certain type (like String, for example) then you should generify Node and subsequently NodeList to prevent type errors.
If you don't, then you leave it up to the user of your NodeList to ensure that she never adds an Integer when the list is only supposed to hold Strings. Generics is primarily about catching type problems at compile time rather than runtime.
It's pretty simple to do so, change something like this:
public class Node {
Object data;
//...
}
to something like this:
public class Node<T> {
T data;
//...
}
public class NodeList<T> {
public Node<T> get(String id) {
//...
}
public boolean add(Node<T> node) {
//...
}
}
Your NodeList looks like it could potentially have a second type parameter for the key type, which right now you're constraining to String.
You can generically type the methods arguments as well as the class itself. Here's an example from Java's java.util.List interface:
public interface List<E> {
//...
boolean add(E e);
//...
}
Generics are a way for Java to force a collection data structure (HashMap in your case) to accept only a specific types of objects. This means that at compile time, if you tried something like:
nodeList.add(1, new Node());
it would fail and not compile since 1 is not a String object. It is generally a way to write tidier code.
Check this link as well:http://en.wikipedia.org/wiki/Generics_in_Java

Categories

Resources