Android Context not serializable dilemma for class that implements Iteratable - java

Here is my situation. I have written a Playlist class that stores a context. Playlist has 9 child classes. Unfortunately, to pass Playlist between intents, it must implement Serializable. This is a problem because Playlist stores a context, so that the Iterator can work, as the Iterator method that must be Overridden from Iterator can not accept any parameters. Therefore, I must store Context somewhere as it is needed to determine the size of the Playlist. Here is the (simplified) code.
public abstract class Playlist implements Serializable, Iterable<Song>
{
private static final long serialVersionUID = 0L;
private Context context;
public Context getContext() { return context; }
public Playlist(Context context)
{
this.context = context;
}
public abstract int size(); //getContext() referenced in all currently written children
public abstract Song getSong(int index); //getContext() referenced in all currently written children
#Override
public PlaylistIterator iterator()
{
return new PlaylistIterator();
}
public class PlaylistIterator implements Iterator<Song>
{
private int current;
PlaylistIterator()
{
current = 0;
}
#Override
public boolean hasNext()
{
return current < size(); //SIZE HERE needs access to a context, but this method certainly can not take one, and neither can the constructor above.**
}
#Override
public Song next()
{
if (!hasNext())
throw new NoSuchElementException();
return getSong(current++);
}
#Override
public void remove()
{
throw new UnsupportedOperationException();
}
}
}
I have read that you can store a static context, but that this is poor design. I can not seem to find a way around this.
I have considered adding a static context reference that is assigned in writeObject, and then accessed in readObject, as the transition should be nearly instant because the Serialization implementation is only so that Playlist can be passed in an intent. But even this feels hacky.
Is there a common work around to dealing with the fact that we cannot serialize context? Is my solution acceptable in terms of stability? It might be against the rules, but what is your recommendation in this situation?

I have written a Playlist class that stores a context
That's probably not a good idea.
Unfortunately, to pass Playlist between intents, it must implement Serializable
It could be Parcelable, but that does not solve your problem. A Context cannot go into either a Serializable or a Parcelable.
because Playlist stores a context, so that the Iterator can work,
That's probably not a good idea.
Therefore, I must store Context somewhere as it is needed to determine the size of the Playlist.
Or, the Playlist could hold the size of the playlist. An int is readily able to be used with Serializable or Parcelable.
Or, get rid of the Iterator, as that is not going to work well with Serializable or Parcelable either.
I can not seem to find a way around this.
Have Playlist be a pure model object, with no Context.
Or, depending on the use case, have Playlist be a singleton, using the Application as the Context. It is unclear whether there is only one Playlist or several.
but what is your recommendation in this situation?
Playlist should not hold a Context and should not have an Iterator.

Related

Accessing attributes, methods of different class objects stored inside an object type Arraylist

I have different weapon classes with various attributes and functions (some of which are similar). I am trying to iterate through objects of classes and trying to access those attributes based on certain conditions. Below are some of the objects I created and am storing inside an ArrayList of type Object.
Ak117 ak117 = new Ak117();
Ak47 ak47 = new Ak47();
Bk57 bk57 = new Bk57();
ArrayList <Object> weaponObjects = new ArrayList<>(Arrays.asList(ak117, ak47, bk57);
int damage = weaponObjects.get(0).damageStats;
//damage stats is an integer inside AK117 class that returns its damage
When I do this Eclipse can't identify .damageStats; and throws an error.
Is there any way wherein I can access all attributes or methods of these objects?
You can use Interface or Abtract class
Example
Create an interface that contains all the common methods of the classes:
public interface Weapon{
int getDamageStats();
void shoot();
// more method
}
Creat class implements this interface
class Ak47 implements Weapon{
#Override
public int getDamageStats() {
return 100;
}
#Override
public void shoot() {
System.out.println("Ak shoot");
}
}
class Bk47 implements Weapon{
#Override
public int getDamageStats() {
return 500;
}
#Override
public void shoot() {
System.out.println("Bk shoot");
}
}
Call List by Weapon:
Ak47 = new Ak47();
Bk47 = new Bk47();
ArrayList <Weapon> weaponsList = Arrays.asList(ak47, bk47);
int damage = weaponsList .get(0).getDamageStats();
you need something like the below:
ArrayList <Weapon> weaponsList = Arrays.asList(ak117, ak47, bk47);
If you only store the Objects you can only call the Object's methods for each array list entry. If you use Weapon (an interface for all weapons that defines getDamageStats()) all subclasses can then have this method called.
You need to write a getter in every weapon class.
public class Ak47 {
int damageStats;
public int getDamageStats() {
return damageStats;
}
}
You can access damageStats in another class by creating an instance of Ak47 and calling the getDamgeStats on it.
public class Example {
Ak47 ak47 = new Ak47();
int example = ak47.getDamageStats();
}
I think you should rethink adding inheritance, I am not a gun expert but maybe by country idk. Another option is with abstract class and just throw the methods that are common and modify the others. Then just like Rob Evans said iterate over a list, but my advise is to use new ArrayList<>(new Ak47(), ...etc) and not Arrays.asList.
Yep, this is a casual problem with the Object class. If you initiate your ArrayList as an Object, as someone already said, you'll only be able to reach Object Class's methods. By what you sent, we can think that your other classes share communs attributes. So the best idea would be to pass by a SuperClass, which will be extended by every others classes and have a getter on it (in this case, a getDamageStats()). Then you initiate your ArrayList as the SuperClass instead of Object and you'll be able to reach what you seem to want

Force a user of my library to implement an interface or extend an abstract class

I'm developing an android library (.aar) and I was wondering if it was possible to, as the title suggest, force a user to implement an interface or extend an abstract class of my library.
I already know that I could just go with a class like this in my library :
public class MyLibrary
{
public interface VariablesInterface
{
void createVariables();
}
private static VariablesInterface vi = null;
public void setVariablesInterface(VariablesInterface v)
{
vi = v;
}
private static void SomeWork()
{
if (vi == null)
{
throw new RuntimeException("You noob.");
}
else
{
// do work
}
}
}
The library will work "alone" at some point, and when it will come to SomeWork(), if the interface isn't implemented it will crash, but this could only be seen at runtime.
Is there a way to have this behaviour when compiling the user's application ?
The goal is to avoid the user forgetting that he have to implement this without having to write it in the documentation and hope the user will probably read it.
Thanks for reading !
EDIT
I think that this question need some enhancement and background.
The purpose of the library is to provide classes that create variables which manages preferences, e.g. :
public class VarPreferenceBoolean extends VarPreference
{
private boolean defaultValue;
public VarPreferenceBoolean(String key, boolean defaultValue)
{
super(key, true);
this.defaultValue = defaultValue;
}
public void setValue(Context context, boolean value)
{
SharedPreferences.Editor e = context.getSharedPreferences(PropertiesManager.preferenceFileName, Context.MODE_PRIVATE).edit();
e.putBoolean(key, value);
e.commit();
}
public boolean getValue(Context context)
{
readPropFile(context);
SharedPreferences sp = context.getSharedPreferences(PropertiesManager.preferenceFileName, Context.MODE_PRIVATE);
return sp.getBoolean(key, defaultValue);
}
}
The same goes for int, string and so on.
In the super class, I add each VarPreference to a List to keep the library acknowledged of all the variables availables.
Note the readPropFile inside the getter.
Then, the user use the library in his project like this :
public class Constants
{
public static final VarPreferenceInt FILETYPE;
public static final VarPreferenceInt DATAMODE;
public static final VarPreferenceString URL_ONLINE;
public static final VarPreferenceBoolean UPDATING;
public static final VarPreferenceLong LAST_UPDATE;
static
{
FILETYPE = new VarPreferenceInt("FileType", MyFile.FileType.LOCAL.getValue());
DATAMODE = new VarPreferenceInt("DataMode", DataProvider.DataMode.OFFLINE.getValue());
URL_ONLINE = new VarPreferenceString("UrlOnline", "http://pouetpouet.fr");
UPDATING = new VarPreferenceBoolean("Updating", false);
LAST_UPDATE = new VarPreferenceLong("LastUpdate", 0L);
}
}
Now, when the user call an accessor, readPropFile will first search if a .properties file exist and modify accordingly the preferences if it found matches between the list of VarPreference and the properties of the file. Then it will delete the file and the accessor will return the value.
This is what exists today.
Now we want another application (let's say Pilot) to be able to get the VarPreferences of the user's application (let's say Client). Both implements the library.
Pilot send an Intent asking for the VarPreference list of Client, putting in extra the package name of Client.
The library receive the intent, verify the packagename, if it's Client it send back the list.
Problem is, if Client hasn't started, no VarPreference exists, and the list is empty.
I need to force the user to create his VarPreference in an method that my library know, to be able to call it whenever I want, and create the VarPreferences of the user when it's necessary.
Hope this is clearer !
EDIT
I rethought about all of this with a colleague and it just hit us that all this stack is biaised.
I didn't explain well and even if I said it, I didn't take account enough of this : everything needs to be done from the library.
So, even if I give an interface to the library, the application will have to run and call this affectation first in order to let the library work alone.
We are heading towards introspection now.
(This is the goal, it may not be possible...)
There will be an abstract class inside the library, with an abstract method where the user will place all of the VarPreferences creations. The user will have to extends this class and call the method in order to create his VarPreferences.
In the library, a method will search by introspection a child of the abstract class, create an instance of this child and call the method that will create the VarPreferences.
I would leave the abstract classes and interfaces in the main library and load the rest of your code via classloader from another. JDBC works like this.
Is there a way to have this behaviour when compiling the user's application ?
I see no way to force a compilation failure. However, if you force them to supply a VariablesInterface in the constructor then it will fail immediately. Make the VariablesInterface be final and only initialize it in the constructor:
public class MyLibrary {
private final VariablesInterface vi;
public MyLibrary(VariablesInterface vi) {
if (vi == null) {
throw new IllegalArgumentException("vi can't be null");
}
this.vi = vi;
}
...
If you can't change the constructor then you can also add to any SomeWork public methods some sort of configuration check method to make sure the the vi wiring has properly been done but this requires careful programming to make sure all public methods are covered.
public void somePublicMethod() {
checkWiring();
...
}
private void checkWiring() {
if (vi == null) {
throw new IllegalStateException("vi needs to be specified");
}
}

Implement java collection without losing information

I have a class that contains two attributes :
#lombok.Data
public class BusinessObjectCollection<T> implements Serializable {
protected List<T> elements;
protected Integer totalCount;
public BusinessObjectCollection() {
this.elements = new ArrayList<>();
this.totalCount = 0;
}
}
I want this class to implements the interface java.util.Collection in order to call remove(), addAll(), and some other methods directly on the BusinessObjectCollection objet.
So I modify my class like this :
#lombok.Data
public class BusinessObjectCollection<T> implements Collection<T>, Serializable{
protected List<T> elements;
protected Integer totalCount;
public BusinessObjectCollection() {
this.elements = new ArrayList<>();
this.totalCount = 0;
}
#Override
public boolean addAll(Collection<? extends T> c) {
return elements.addAll(c);
}
#Override
public boolean removeAll(Collection<?> c) {
return elements.removeAll(c);
}
[...]
}
My problem is that if I do this, my object lose some informations. I can't see the "elements" and "totalCount" attributes.
Is it possible to use the Collection interface and keep this attributes ?
If no, is there a good alternative ?
You are viewing a feature in your IDE. In your case probably IntelliJ.
When it encounters a Collection, it will only show the contents of the collection and not the actual implementation. This is very useful most of the time, because you are using Collections that might have very complex structures, such as HashSet. But when developing your own collection, you want to see that actual workings in the debugger.
In IntelliJ this is called 'Alternative view for Collection classes'. The manual explains how to disable this.
In Eclipse this is also available (but seems to be turned off by default). The feature is called Logical Structures. This view can be enabled with a toggle button ('Show Logical Structure') in the Variables View.

What is the way to create API Library in Java

I am creating an API of a list of checking functions. There is an object passed in as an argument to be checked.
The object is like below:
public class People{
private String name;
private String address;
private int age;
private String job;
public getter() ...
public setter() ...
}
I create a class including a list of checking function to make sure the provided information is valid or not. For example:
public class checkingFunctions {
public static boolean checkName(People ppl){
perform the name checking function;
}
public static boolean checkAge(People ppl){
perform the age checking function;
}
}
I know the above way works as an API so that other people can call checkingFunctions.checkName(ppl). But is this the correct way to build the API that will be exposed to others as jar file ? I was thinking to create an interface of checkingFunctions like below:
public interface ICheckingFunctions {
boolean checkName(People);
boolean checkAge(People);
}
And let the checkingFunctions class to implement it, like
public class checkingFunctions implements ICheckingFunctions {
}
BUt it won't compile because the checkName and checkAge can not be declared as static if it is overriding a superclass method.
Or should I just use the interface and let it implement the interface, but remove the static from all checking method. So, if others want to use my API, they just instantiate the interface, and use instance.checkName() to call method ? is that a good way ?
I am wondering whether there there exists an industry standard or design pattern standard to create such an interface so that others can call it.
Thanks a lot.
How to design such an API very much depends on how your API is intended to be used.
If it for example turns out, that your People class is best implemented as a final class, and you want to make sure, that it is always checked in the same consistent way, then providing a number of public static check... methods is certainly a reasonable way to go.
If on the other hand you do not know in advance how your People class should be checked, then I'd consider providing an ICheckingFunctions interface that declares the necessary check... methods. But if you go this route, you will perhaps also need to provide a way for the user to change the actually used implementation of ICheckingFunctions.
You should also consider, that while using an interface is certainly much more flexible and extensible, it is also more work to maintain and it could also provide a possible security risk - e.g. if you allow users to change the used ICheckingFunction, then you no longer have control of how your People class is checked.
One possible way to implement such an API using an interface is allowing users to register/unregister the used ICheckingFunction in your class. A very naive implementation could look like this:
public final class CheckingFunctions {
private static ICheckingFunctions checkFunction;
public static void registerCheckFunction(ICheckingFunctions checkFunction) {
CheckingFunctions.checkFunction = checkFunction;
}
public static boolean checkName(People ppl){
return checkFunction.checkName(ppl);
}
public static boolean checkAge(People ppl){
return checkFunction.checkAge(ppl);
}
}
This is of course just a minimal example. In an actual API you would have to decide quite a lot of additional details. For example:
Is there only ever a single ICheckingFunctions instance available? If there may be more registered ICheckingFunctions - how do you choose which of these functions are used?
Who is allowed to register/unregister an ICheckingFunctions instance?
May the ICheckingFunctions be called from different threads?
etc.
You must also consider in which environment your API is going to be used. If you for example want to support usage of your API in an OSGI environment, then you could e.g. supply your ICheckingFunctions as an OSGI service.
Last but not least I would consider the following: May your users subclass the People class? If yes, then it would perhaps be a good idea to make the ICheckingFunctions interface generic, and allow registrations of implementations for different classes. Here again a very naive example of this approach:
public final class CheckingFunctions {
public interface ICheckingFunctions<T extends People> {
boolean checkName(T p);
boolean checkAge(T p);
}
private static Map<Class<?>,ICheckingFunctions<?>> checkFunctions = new ConcurrentHashMap<>();
public static <T extends People> void registerCheckFunction(ICheckingFunctions<T> checkFunction, Class<T> c) {
checkFunctions.put(c, checkFunction);
}
private static <T extends People> ICheckingFunctions<T> getRegisteredCheckFunction(Class<T> c){
ICheckingFunctions<T> checkFunction = (ICheckingFunctions<T>) checkFunctions.get(c);
if (checkFunction == null) {
// provide some reasonable default?
throw new IllegalStateException();
}
return checkFunction;
}
public static <T extends People> boolean checkName(T ppl, Class<T> c){
return getRegisteredCheckFunction(c).checkName(ppl);
}
public static <T extends People> boolean checkAge(T ppl, Class<T> c){
return getRegisteredCheckFunction(c).checkAge(ppl);
}
}

Extending a non-generic class to a generic class

The Java class CircularFifoBuffer in the package org.apache.commons.collections.buffer is non-generic, and can store objects of any class.
I would like to create a generified version of this, that can only hold objects of class T. My first thought was to extend CircularFifoBuffer and simply write a new 'add' method:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
public boolean add(T data) {
return super.add(data);
}
}
However, this leaves the old 'add' method in place, allowing for objects of arbitrary class to be added. Is there a way around this that uses inheritance rather than composition (so that I don't have to re-implement all of CircularFifoBuffer's methods) but prevents users of the class from adding non-T objects?
One idea is t implement your own buffer that just wraps the original one:
public class CircularFifoQueue<T> {
private CircularFifoBuffer buffer = new CircularFifoBuffer();
public boolean add(T data) {
return buffer.add(data);
}
// implement all other methods that are needed
}
So the internal buffer takes everything but the wrapper makes sure that only T type objects can be added. Problem: right now the buffer does not implement any interface. So it's usage is a bit limited right now (you can't use it if you need to send a Buffer for example)
No, you can't.
The simple reason why this isn't possible is polymorphism. If you could remove the add(Object) method, you would break polymorphism for the CircularFifoBuffer class.
Here is a simple example. For this to work correctly, your CircularFifoQueue class needs to have a add(Object) method.
CircularFifoBuffer buffer = new CircularFifoQueue<String>();
buffer.add(new Object());
#Vivien's answer already explains why it doesn't really make sense to do this (for more information, read about the Liskov substitution principle).
However, you could hack around this by defining a custom override of add(Object) that simply throws an exception at run-time. It's not a very elegant solution, but if you want a quick fix, then this might be it.
You can try the following approach. It is not very elegant, but it should do the job:
public class CircularFifoQueue<T> extends CircularFifoBuffer {
private Class<T> klass;
public CircularFifoQueue(Class<T> klass) {
this.klass = klass;
}
#Override
public boolean add(Object data) {
T typedData = klass.cast(data);
return super.add(typedData);
}
public boolean add(T data) {
return super.add(data);
}
}
...
CircularFifoQueue<String> queue = new CircularFifoQueue<String>(String.class);
queue.add("hello"); // should work
queue.add(123L); // should throw ClassCastException
Anyway, implementing a class that delegates its method calls is not very hard. Any decent IDE will autogenerate that for you.

Categories

Resources