Without getting bogged down with specifics, my code represents a library whereby each book is made up of a Set of pages containing a Set of Words.
I have created my own Set implementations:
class PageSet<E> extends HashSet<E>(){
public boolean set(int index, E e){....}
....
}
and
class WordSet<E> extends HashSet<E>(){
public boolean set(int index, E e){....}
....
}
I've got stuck when I try to create a Book in my main class:
Set<Set<Word>> dictionary = new PageSet<WordSet<Word>>();
Which results in a type conversion mismatch. However it will quite happily accept
Set<Set<Word>> dictionary = new PageSet<Set<Word>>();
Could someone please shed some light as to what I'm doing wrong when using a generic setup like this?
Basically, a PageSet<WordSet<Word>> is not a Set<Set<Word>>, because X<Subclass> is not a X<Superclass>.
If you had said
Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();
then that would have worked also.
It's either
Set<Set<Word>> dictionary = new PageSet<Set<Word>>();
or
Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();
Since although WordSet is a subclass of Set, a Set<WordSet> is not a subclass of Set<Set>.
In other words, generics are not covariant, which is different from things like arrays.
In any case, you should not extend collections unless you are trying to create new collection types. Since you cannot restrict the visibilities of superclass methods in a subclass, people will be able to write
WordSet<Word> words = ...;
words.clear();
You probably do not want to give clients that power. Instead, use aggregation instead of inheritance.
class Word {
private String text;
private PartOfSpeech part;
// Constructors, getters, setters, equals, hashCode are elided.
}
class Page {
private int pageNumber;
private Set<Word> contents = new HashSet<>();
public class Book {
private String title;
private List<Page> pages = new ArrayList<>();
}
Pages in a book are ordered linearly, which is why I used lists. I'm not sure why you used sets. But in any case, by encapsulating the collections inside the classes, you can provide client code exactly the interface you want them to use. The visibilities were chosen deliberately; this looks like a cluster of related classes, but you might want to change them.
Related
I'm fairly new to programming and we do have an exercise, we have to use the Consumer interface, we have a generic class (genClass) that has a Consumer<T> attribute (conAtt). In another class we have to use the accept method of Consumer, but somehow it doesn't work. I have already read through the Java API of the Consumer interface, but it didn't help.
The error message says:
The method accept(capture#4-of ?) in the type Consumer<capture#4-of ?> is not applicable for the arguments (capture#5-of ?)
I know it says not applicable, but why not?
public abstract class GenClass<T> {
protected Consumer<T> conAtt;
public abstract T getData();
}
class Otherclass{
private List<GenClass<?>> helparray= new ArrayList<>();
private void testmethod() {
Iterator<GenClass<?>> hilfe = helparray.iterator();
while (hilfe.hasNext()) {
GenClass<?> help = hilfe.next();
help.conAtt.accept(help.getData());//here is the problem
}
}
}
public class thirdclass extends GenClass<Character> {
#Override
public Character getData() {
return 't';//t is just an example
}
}
This is not really a question about how the Consumer - or other interfaces - in Java work, but about Generics.
Generics aim to simplify the way of writing code and avoid code repetitions. E.g. you need to do a similar task, but for different types you can write it once by using Generics instead of writing it over and over again, just with concrete types being replaced.
For example one day you have the need to keep track of a list of Strings. As easy as that, your going ahead and implementing a solution for that, whereby the first implementation can look like the following (note: a very simplified example, but it'll show the purpose):
public class CustomListString {
private String[] elements = new String[10];
public void add(String newElement) {
int nextFreeIndex = findNextFreeIndex();
elements[nextFreeIndex] = newElement;
}
public String get(int index) {
return elements[index];
}
}
So you can use the above implementation of the List in your code like the following:
public static void main(String[] args) {
CustomListString listOfStrings = new CustomListString();
listOfStrings.add("A");
listOfStrings.add("B");
}
Simple, specific and sufficient!
But the other day, you also have the requirement to keep track of a list of Integers. What to do now?
A way to solve this is to just repeat your previous approach and to implement another CustomList only for the Integers now. Where the corresponding implementation would look like this (the implementation of CustomListString has been copied and all occurrences of String have been replaced by Integer):
public class CustomListInteger {
private Integer[] elements = new Integer[10];
public void add(Integer newElement) {
int nextFreeIndex = findNextFreeIndex();
elements[nextFreeIndex] = newElement;
}
public Integer get(int index) {
return elements[index];
}
}
As you can imagine now already, this is not flexible and can be very cumbersome in the future. This approach will require a new implementation of each type you want to store in the future. So you might end up to also create implementations like CustomListDouble, CustomListCharacter, ... and so on, in which only the type of the elements within the array change - nothing else which would be of importance!
This will additionally lead to the situation, that you'll duplicate a lot of similar code (like findNextFreeIndex() method would have been) and in case of a bugfix need to adjust it in a lot of places instead of in only one.
To solve this issue and remain the type safety in the CustomList.get method Generics have been introduced to Java!
With the Generics approach you'll be able to create a single implementation of the CustomList to store all of your data types without unnecessarily duplicating any shared, basic code and remain the type safety!
public class CustomList<T> {
private Object[] elements = new Object[10]; // Java doesn't supprort easily support generic arrays, so using Object
// here. But the compiler ensures only elements of the generic type T
// will end up here
public void add(T newElement) {
int nextFreeIndex = findNextFreeIndex();
elements[nextFreeIndex] = newElement;
}
#SuppressWarnings("unchecked")
public T get(int index) {
return (T) elements[index];
}
}
Using the new list following the Generics approach we can use it like this now:
public static void main(String[] args) {
CustomList<String> genericList = new CustomList<>();
genericList.add("Hello World");
genericList.add(5); // Compile error! Integer and String types cannot be mixed in
// a single instance of the list anymore => Nice, prevents errors!
genericList.get(0).substring(6); // No compile error, also the compiler knows Strings
// are contained in the list
}
The generic CustomList can now also be reused for any other type and still provide type safety.
What does it mean for your implementation
You can see how we specified the generic type in the CustomList class as T - this is similar like you specified it with ? (probably you'll also want to replace it with T, since you'll run into other issues later when working with the Consumer). But when we used the implementation in our other classes, it wouldn't have been possible to specify it as CustomList<T> or CustomList<?> anymore. We needed to decide and specifiy which exact type of elements the list should contain. This has been the String class, so we specified it as CustomList<String>.
Note: ? is a generic wildcard and means something like "I don't know the real type of the classes now and I'll also don't know it in the future". That's why it'll be hard for you working with the concrete types later in the Consumer. You'll be not able to call any conrete methods on your objects therein. Therefore ? should be avoided as a generic type argument and something like T should be used instead. T means something like "I don't know the real type of the classes now, but I'll do later, as soon as you tell me". Therfore you'll be able to call concrete methods on the objects later in the Consumer, what will simplify your work there a lot.
For your code this means, wherever you want to use your implementation of GenClass<T> you need to specify with which exact kind of elements the class is going to work with. In case of String it is GenClass<String> in case of Character GenClass<Character>.
So the place you'll need to replace the occurrences of GenClass<?> is wherever you refer to it in Otherclass and Otherclass.testmethod.
The way you used the Consumer is fine
This is my first problem I can't solve by searching. It's a general OOP problem, but the code is in java. Perhaps I miss an essential point?
Assume there is a baseclass and a subclass. An object of the baseclass is in many lists. There is a transformer class with one duty to transform the object into a subclass object. The transformer should not know anything about the lists. But as a result of the transformation the new subclass object should be in all the lists. (replace the former base class object)
Can this be done somehow?
class BaseClass {
//
}
class SubClass extends BaseClass{
//
}
class Transformer{
BaseClass base;
public Transformer(BaseClass base){
this.base = base;
}
public void transform(){
//transforms the Object to a subtype-object
// ???
// (move the references of the old object to the new one)
this.base = new SubClass(); //something like this (but not so!!!)
}
}
class Programm{
private List<BaseClass> list1 = new ArrayList<>();
private List<BaseClass> list2 = new ArrayList<>();
private List<BaseClass> list3 = new ArrayList<>();
//many more Lists
private List<BaseClass> listn = new ArrayList<>();
public void main() {
BaseClass myObject = new BaseClass();
list1.add(myObject);
list2.add(myObject);
list3.add(myObject);
listn.add(myObject);
Transformer transformer = new Transformer(myObject);
transformer.transform();
//required result
// All Lists contain the transformed Object (from Type SubClass)
}
}
What you're trying to do is luckily impossible (imagine if your objects started changing classes in the middle of your code). You can create a subclass object based on a superclass object (if you can sensibly fill in any missing properties), but you can't turn an existing object into its subclass (such that the reference equality would work as you're hoping in your example code, i.e. converting myObject would affect all the lists).
I don't know how you came up with this idea, but somewhere along the way you've gone down the wrong path. If you tell us what you're trying to achieve, we can provide you with a better solution.
Edit:
Since you're doing checkers and you need to crown a piece, you have the simple choice of adding a boolean crowned property to pieces, and writing logic based on that.
In a more complex situation you could for example use the strategy pattern, where you would have a Piece class, and they would have a Type property that specifies the actual type of the piece. This way the object you put in lists (Piece) always stays the same, but if you replace its Type property, it would seem as if the piece magically changes it's type!
I am looking for a way to save a list of objects to the database with ORMLite and read upon this question: Best way to store several ArrayLists in ORMLite for ApplicationSettings
And the accepted answer makes sense to me:
public class YourClass {
#GeneratedId
private int id;
#ForeignCollectionField
private Collection<MyString> bunchOfStrings = new ArrayList<MyString>();
}
public class MyString{
#DatabaseField(canBeNull = true, foreign = true)
private YourClass yourClass;
#DatabaseField
private String text;
}
And the only thing that I don't understand is this line private Collection<MyString> bunchOfStrings = new ArrayList<MyString>(). Why do we save the ForeignCollectionField as Collection<MyString> instead of as ArrayList<MyString>? When working with the bunchOfStrings object above, do we always need to cast it to ArrayList<MyString>?
Why do we save the ForeignCollectionField as Collection
instead of as ArrayList?
That was design consideration, excerpt from doc
The field type of orders must be either ForeignCollection<T> or Collection<T> – no other
collections are supported because they are much heavier with many methods to support
When working with the bunchOfStrings object above, do we always need
to cast it to ArrayList
You dont have to initialize that field, Ormlite will do that. Hence, only available methods are ones present in Collection or ForeignCollection
I am writing a program to simulate cities from a game called Civilization 4. In order to do this I have several Enums to represent types of terrain, resources, improvements etc for each plot owned by said city.
The problem is I want to program to be compatible with Fan made mods which may add things to the Game that need to be accepted into my independant utility. So I thought of creating a Enum style class to hold the new types defined by the loaded mods (as Enums cannot be changed at runtime) which is created during runtime when the user enters in a mod to be loaded (which is a txt file that is parsed to read the new additions)
So is there a way to simulate Enums that are created and added to at runtime? I take it static member variables cannot be used as they are done before runtime...
You can make a enum implement an interface.
This way you can have your defined values in the enum, but new values can be any class which implements the interface.
An alternative is that you generate or load the enum at runtime using a byte code generator or the Compiler API. I wrote a library to make it easier to take a String and compile&load it.
http://vanillajava.blogspot.co.uk/2010_11_01_archive.html
Well, enums in Java are simply classes where the language guarantees that the set of known objects is known and limited at compile-time. If you want to add new enum literals at runtime, you end up with regular classes.
The beauty of enums is that you can write human readable names in code that are compiled as numbers behind the scenes, because computers like numbers better. Take for example this enum:
enum Season { WINTER, SPRING, SUMMER, AUTUMN }
Behind the scenes WINTER might be 0 (zero), SPRING is 1 etc.
To replicate this behaviour in runtime code you could create a list of strings, like this:
List<String> seasons;
seasons = new ArrayList<String>();
seasons.add("Winter");
seasons.add("Spring");
...
That way you can reference the items as numbers, such as seasons[1] would equal "Spring".
This answer is just one of many ways to approach this question.
By default, enum types have only a set number of values. The values in an enum type are actually declared as static final, and there's no way to add more on runtime.
That being said, there are other patterns you can use to implement what you want. Let's take a look at using an interface and a registration system. We'll start with the Terrain interface:
public interface Terrain {
int getId();
String getName();
int getSightBonus();
}
Now an enum, DefaultTerrain:
public enum DefaultTerrain implements Terrain {
PLAINS(0, "Plains", 1),
HILLS(1, "Hills", -1),
MOUNTAINS(2, "Mountains", -2);
private int id;
private String name;
private int sightBonus;
private DefaultTerrain(int id, String name, int sightBonus) {
this.id = id;
this.name = name;
this.sightBonus = sightBonus;
}
public int getId() {return id;}
public String getName() {return name;}
public int getSightBonus() {return sightBonus;}
}
And a registration class, which can be either a static utility class or a singleton.
public class TerrainManager {
private static Map<Integer, Terrain> terrainsById = new HashMap<>();
static {
for (DefaultTerrain terrain : DefaultTerrain.values())
register(terrain);
}
public static void register(Terrain terrain) {
Integer id = terrain.getId();
if (terrainsById.contains(terrain.getId()))
throw new IllegalArgumentException("Terrain with id already exists: " + id);
terrainsById.put(id, terrain);
}
public static Terrain getTerrainById(int id) {
return terrainsById.get(id);
}
public static Set<Terrain> getAllTerrains() {
return new HashSet<Terrain>(terrainsById.values());
}
}
This last class is where the magic happens. Presumably the modders will have some kind of identifier in the game's world definition to say "use this tile," right? In this case, I've called it an integer, id, but really it could be any type, just modify the Map accordingly. In the map-loading code, just use the ID in the world definition to look up the Terrain. When a modder adds a new Terrain, they just need to implement Terrain and register it with TerrainManager.
The static initializer makes sure that your DefaultTerrain objects are added before anything else is added. If you use a singleton, this could be put into the class constructor instead.
Use this pattern for your different enum types that you want users to add to. You could also use it for pretty much any other type as well besides enum.
You will need CGLIB, http://cglib.sourceforge.net/
Can somebody explain me what "hidding api with interfaces in Java" means ?
How can I use the API functions by means of interfaces ?
I would need an small working example to understand the how the interfaces hides the api non public parts, and how can I use the api puplic parts in the same time.
Thanks in advance.
THANKS GUYS FOR THE QUICK REPLY, GIVE ME TIME TO THINK OVER THE ANSWERS.
LAST BUT NOT LEAST THANKS FOR YOUR TIME AND EFFORT!
II. My second question is : What happens in the background this case below ?
IBinaryOperation op = BinaryOperationProvider.getOperation("multiply");
or
List<String> myList = new LinkedList<String>();
Its not clear for me because the interfaces consist of methods' declarations that's why i dont understand what could happened in the lines above.
Is there any meaning of the equality between empty method of used interfaces and objects ?
Sorry for my weak English.
For instance, you may declare and create a list of strings as follows:
List<String> myList = new LinkedList<String>();
List is the type of myList. It is an interface. It means that all subsequent calls to methods of myList will be done through the interface: you may only call methods declared in the List interface.
However, the concrete class of the object is LinkedList, that contains more methods, some of them reflecting the structure of a linked list (for instance addFirst and addLast). But these methods are hidden because of the way you declared the variable. You chose to access the object through a given (restrictive) interface.
It may seem restrictive, but it also means that you can change your code at any time, and replace the concrete class LinkedList with any other class that implements the List interface, for example ArrayList.
Usually when you expose your API, you should hide the implementation details as much as possible and expose it via simple interfaces.
For e.g. Suppose that you give an api for adding two numbers.
Soln1 (Bad soln) Give the following class to client
public class Adder {
public void setA() {..}
public void setB() {..}
public int add() { return A + B; }
}
Soln 2 (better soln): Give the following interface to the client.
public interface Adder {
public int add(int a, int b);
}
Now why is soln 2 a better solution. If you had given user the first soln. The client is bound to the class Adder. Suppose later you have a new implementation of addition that could add the numbers in the cloud(over-imaginative :)), you may have to as the client to change their code to use the new class.
Instead if you just give them the interface, you could provide many implementation and have a factory mechanism to choose the suitable implementation.
Here's a very simple example that uses an interface:
public interface IBinaryOperation {
public int performOp(int a, int b);
}
private class MultiplicationProvider implements IBinaryOperation {
public int performOp(int a, int b) {
return a * b;
}
}
public class BinaryOperationProvider {
static IBinaryOperation getOperation(String name) {
if ("multiply".equals(name)) {
return new MultiplicationProvider();
} else if ("add".equals("name)) {
return new AdditionProvider();
} // ...
}
}
You would use this like:
IBinaryOperation op = BinaryOperationProvider.getOperation("multiply");
int c = op.performOp(a, b);
In the above example, MultiplicationProvider is completely private to the implementation of the API. The only public part is the IBinaryOperation interface, and the BinaryOperationProvider class.
Just to be clear, what's "hidden" is not the API, but the implementation. Most clients of List (to use an example above) don't need to know which kind of List is actually being used. (Just like most TCP/IP clients don't need to know anything in particular about the network they're using -- just that it supports the standard connection abstraction.)