List of inheriting objects java - java

I created a little example. Imagine I have two classes:
public class Neuron {
ArrayList<Neuron> neighbours = new ArrayList<>();
int value = 1;
public Neuron() {
}
public void connect(ArrayList<Neuron> directNeighbours) {
for (Neuron node : directNeighbours) {
this.neighbours.add(node);
}
}
}
and a class that inherits from Neuron:
public class SpecialNeuron extends Neuron {
int value = 2;
public SpecialNeuron() {
}
}
In my case, I want the inheritance in order to avoid a lot of "if object is special do something" stuff. However, when I am calling:
public static void main(String[] args) {
ArrayList<Neuron> neurons = new ArrayList<>();
Neuron a = new Neuron();
Neuron b = new Neuron();
Neuron c = new Neuron();
neurons.add(b);
neurons.add(c);
a.connect(neurons);
ArrayList<SpecialNeuron> special = new ArrayList<>();
SpecialNeuron d = new SpecialNeuron();
SpecialNeuron e = new SpecialNeuron();
special.add(d);
special.add(e);
a.connect(special); //Error
}
it is not possible to use a List(SpecialNeuron) for a List(Neuron) parameter. What is wrong with this call, and is there a proper way to solve that issue?
Furthermore, I could do
ArrayList<Neuron> special = new ArrayList<>();
Neuron d = new SpecialNeuron();
Neuron e = new SpecialNeuron();
special.add(d);
special.add(e);
a.connect(special); //works fine
Which works, but denies any usage of functions from the SpecialNeuron class.

You can make use of WildCards in Generic <? extends T>.You can read more about it here.
Change your method param to this.
public void connect(ArrayList<? extends Neuron> directNeighbours) {
for (Neuron node : directNeighbours) {
this.neighbours.add(node);
}
}

First of all, you're extending Neuron class, but you're not really using inheritance. You should make value variable protected and set its value in constructor.
public class Neuron {
protected int value;
public Neuron() {
this.value = 1;
}
}
public class SpecialNeuron extends Neuron {
public SpecialNeuron() {
this.value = 2;
}
}
Now, your problem is on the line 17 - ArrayList<SpecialNeuron> special = new ArrayList<>(); - you have List of SpecialNeuron objects, that are children of Neuron class, so Java knows it contains only objects of class SpecialNeuron
In your connect() function, you accept only Neuron class objects, so in order to make it work, you have to change your special list to:
ArrayList<Neuron> special = new ArrayList<>();
In this List, you can add Neuron and SpecialNeuron objects and use it as a List of Neuron objects.

Related

Java OOP; creating array of objects

I'd like to create an array of objects where 3 objects are from one class, and a 4th is from second class.
In the first class I did the following:
public class Pupil {
public int n= 0;
Pupil(int n) {
this.n = n;}
}
in the second class I did the following:
public class Tutor {
public int m= 0;
Tutor(int m) {
this.m = m;}
}
In the main class, I created several pupil objects and one tutor object, like this:
public class Main {
public static void main (String[] args) {
//Pupil(n) while for tutor objects it'd be Tutor(m)
Pupil pupil1 = new Pupil(9);
Pupil pupil2 = new Pupil(8);
Pupil pupil3 = new Pupil(6);
Tutor tutor1 = new Tutor(2);
Using objects for printing in main works fine.
But I'd like to create a fourth class where I group them into arrays of objects, but it won't see the objects that I created to create groups out of them. I'm also not sure about the format for creating an array of objects.
public class Groups {
public static void main(String [] args){
Pupil [] g1 = {tutor1, pupil1, pupil2, pupil3};
//cannot resolve any symbols
}
}
EDIT: according to my tutor the groups class should be static to solve this, but I'm not sure how to actually code this?
Edit2: an answer pointed that the array should be Object as the above code would only be able to create an array of pupils, not pupils and tutors objects.
Object [] g1 = {tutor1, pupil1, pupil2, pupil3};
but that still doesn't solve the main issue where no objects are seen from the groups class (//cannot resolve any symbols)
Arrays can only contain the same type of object. With that being said, here is a way:
Object[] g1 = {tutor1, pupil1, pupil2, pupil3};
Java is a strongly typed programming language so you cannot add different type objects to a same collection. But you take advantage of OPP polymorphism principle. You can create a parent class and extend your subclasses from parent class.
Parent Class
public class Group {
}
Child Classes
public class Pupil extends Group {
public int m = 0;
public Pupil(int m) {
this.m = m;
}
}
public class Tutor extends Group {
public int n = 0;
public Tutor(int n) {
this.n = n;
}
}
So this way you can use it as follows:
public class TestSchool {
public static void main(String[] args) {
Pupil pupil1 = new Pupil(9);
Pupil pupil2 = new Pupil(8);
Pupil pupil3 = new Pupil(6);
Tutor tutor1 = new Tutor(2);
Tutor tutor2 = new Tutor(2);
Group[] groupArray = {pupil1, pupil2, pupil3, tutor1, tutor2};
}
}

Java array list returning 0 value

I have created a class like this, which contains a bunch of arraylist as you can see. I've been setting the array with the methods add.. and then retrieving it with get.., when i tried to System.out.println numberofcitizen for example it is returning 0. Note that i have instantiated the class in another class to set the values.
public int numberOfCitizen;
private final ArrayList<Integer> citizenid = new ArrayList<>();
private final ArrayList<String> citizenName = new ArrayList<>();
private final ArrayList<Integer> citizenWaste = new ArrayList<>();
private final ArrayList<Float> longitude = new ArrayList<>();
private final ArrayList<Float> latitude = new ArrayList<>();
private final ArrayList<String> address = new ArrayList<>();
public void working() {
System.out.println("executing fine");
}
public void setnoOfcit(int number) {
this.numberOfCitizen = number;
}
public int getnumber() {
return this.numberOfCitizen;
}
public void addCitizenId(int citizen) {
citizenid.add(citizen);
}
public int getCitizenid(int i) {
int citId = citizenid.get(i);
return citId;
}
public void addCitizenName(String citizenname) {
citizenName.add(citizenname);
}
public String getCitizenName(int i) {
return citizenName.get(i);
}
public void addCitizenWaste(int waste) {
citizenWaste.add(waste);
}
public int getCitizenWaste(int i) {
return citizenWaste.get(i);
}
public void addLatitude(float lat) {
latitude.add(lat);
}
public float getLat(int i) {
return latitude.get(i);
}
public void addlng(float lng) {
longitude.add(lng);
}
public float getlng(int i) {
return longitude.get(i);
}
com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder vrpBuilder = com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.Builder.newInstance();
public void runVPRSolver() {
System.out.println(numberOfCitizen);
System.out.println(getCitizenName(0));
//create a loop to fill parameters
Probable source of problem :
numberOfCitizen is a member attribute that you seem to never change. If you want it to represent the number of elements in your lists, either use citizenName.size() or increment the value of numberOfCitizen in one of the add methods.
Design flaw :
Your design takes for granted that your other class always use that one properly. Anytime you or someone uses that class, he must make sure that he add every single element manually. This adds code that could be grouped inside your class, which would be cleaner and easier to maintain.
So instead of several add method like this :
addCitizenid();
addCitizenName();
addCitizenWaste();
addLongitude();
addLatitude();
addAddress();
Design an other Citizen class which will contain those elements, and use a single list of instances of that class. That way you can use only one method :
private List<Citizen> citizenList = new ArrayList<>();
public void addCitizen(Citizen c) {
/*Add element in your list*/
citizenList.add(c);
}
This programming methodology is called "Encapsulation" which you can read about here
You need to increment numberOfCitizen in your add methods. For example:
public void addCitizenId(int citizen){
citizenid.add(citizen);
numberOfCitizen++;
}
I would also suggest encapsulating your variables into Objects, so create a citizen class:
public class Citizen {
private Integer id;
private Integer name;
private Integer waste;
}
And change your variable to an ArrayList of objects:
ArrayList<Citizen> citizens;

I need a way to randomize outcomes passing and holding classes

I'm trying to add let's say 5 classes that they all extend a General class and implements an init() method in a different way.
What I need is a way to store those classes while passing a number of chances for that Class to "happen"
For this I created a Class holder:
public class ClassHolder {
private Class<? extends GeneralOutcome> holdClass;
private int chances;
public ClassHolder(Class<? extends GeneralOutcome> holdClass, int chances) {
super();
this.holdClass = holdClass;
this.chances = chances;
}
public Class<? extends GeneralOutcome> getHoldClass() {
return holdClass;
}
public void setHoldClass(Class<? extends GeneralOutcome> holdClass) {
this.holdClass = holdClass;
}
public int getChances() {
return chances;
}
public void setChances(int chances) {
this.chances = chances;
}
}
Also a GeneralOutcome class that the ones that will be added to a list will extend:
public class GeneralOutcome {
public void init(String text, int times) {
}
}
And the way I'm adding them to a list:
public class Randomizer {
private static List<ClassHolder> myList = new ArrayList<ClassHolder>();
private static ClassHolder outcome01 = new ClassHolder(Outcome01.class, 10);
private static ClassHolder outcome02 = new ClassHolder(Outcome02.class, 10);
private static ClassHolder outcome03 = new ClassHolder(Outcome03.class, 10);
private static ClassHolder outcome04 = new ClassHolder(Outcome04.class, 10);
private static ClassHolder outcome05 = new ClassHolder(Outcome05.class, 10);
public static void main(String[] args) {
for(int i = 0; i < outcome01.getChances(); i++) {
myList.add(outcome01);
}
for(int i = 0; i < outcome02.getChances(); i++) {
myList.add(outcome02);
}
for(int i = 0; i < outcome03.getChances(); i++) {
myList.add(outcome03);
}
for(int i = 0; i < outcome04.getChances(); i++) {
myList.add(outcome04);
}
for(int i = 0; i < outcome05.getChances(); i++) {
myList.add(outcome05);
}
System.out.println(myList.size());
int rand = (int) (Math.random() * myList.size());
System.out.println(rand);
ClassHolder theHoldClass = myList.get(rand);
System.out.println(theHoldClass.getHoldClass());
Class<? extends GeneralOutcome> theOutcome = theHoldClass.getHoldClass();
theOutcome.init();
}
}
The problem is that I'm not able (Don't know how really) cast back to GeneralOutcome to I can access the .init() method.
I get The method init() is undefined for the type Class<capture#3-of ? extends GeneralOutcome>
I know this isn't the best way to do this. So I'm open to both, a fix for this and also what would be a better way to achieve something like this.
What you are trying to do here doesn't work for some reasons.
First of all, your init method isn't static. So that call
Class<? extends GeneralOutcome> theOutcome = theHoldClass.getHoldClass();
theOutcome.init();
leads directly to a compile-time error.
But then, the whole design looks strange. What is the point of holding Class objects in the first place?
Why don't you create an interface
public interface OutcomeFunctionality {
public void foo(String text, int times);
}
to later instantiate objects of whatever class implementing that interface? So that you can finally can deal with lists of such objects (together with those probabilities)?
[ I used the name foo on purpose: alone the strange name "init" makes it very unclear what your code is intended to do! In that sense you should rethink your design, and find better method names to express what those methods will be doing! ]
Long story short: using/holding Class objects doesn't buy you anything in your example code - it only adds complexity. So my advise is: start working there and get rid of that "detour". You might also want to read about the Open/Closed principle - that could give you some guidance how a good OO design looks like that uses abstract classes / subclassing in order to split "behavior" between base and derived classes.

Count Number of Objects in Java

I am creating a program called Humans and Pets. The program simply prints out a list of Human's names (in this case I have created 4) and their corresponding pets. Here is the code:
AmazingPets.java
public class AmazingPets {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Welcome to Pets and Humans! Created By Marc B.\n____________________________\n");
Dogs firstDog = new Dogs("Ghost");
Humans firstName = new Humans("Alex");
Dogs secondDog = new Dogs("Paperbag");
Humans secondName = new Humans("Michael");
Cats firstCat = new Cats("Tom");
Cats secondCat = new Cats("Mr Furball");
Humans thirdName = new Humans("Bryan");
Humans fourthName = new Humans("Julie");
System.out.printf("%s's dog's name is %s.\n", firstName.getHumanName(), firstDog.getDogName());
System.out.printf("%s's dog's name is %s.\n", secondName.getHumanName(), secondDog.getDogName());
System.out.printf("%s's cat's name is %s.\n", thirdName.getHumanName(), firstCat.getCatName());
System.out.printf("%s's cat's name is %s.\n", fourthName.getHumanName(), secondCat.getCatName());
}
}
Humans.java
public class Humans {
private String mHumanName;
public Humans(String humanName) {
mHumanName = humanName;
}
public String getHumanName() {
return mHumanName;
}
}
I would like to create a class method called populationCount for Humans that would return the total number of Humans instances created. I would then like to output the result (using a Scanner in AmazingPets.java) to have the number of counts in the console.
Can anyone please suggest possible ways to return the total number of Humans made? as I cannot seem to find any resources online. Thank you in advance. :)
You can use this abstract class, in order to count any type of objects that inherits it. The answer is based on addy2012's answer (Thanks!):
public abstract class Countable
{
private static final Map<Class<?>, Integer> sTotalCounts = new HashMap<>();
public Map<Class<?>, Integer> getCountsMap() {
return sTotalCounts;
}
public int getTotalCount()
{
return sTotalCounts.get(this.getClass());
}
public Countable()
{
int count = 0;
//Add if it does not exist.
if(sTotalCounts.containsKey(this.getClass()))
{
count = sTotalCounts.get(this.getClass());
}
sTotalCounts.put(this.getClass(), ++count);
}
}
Then, you can do:
public class Dogs extends Countable {/**/}
public class Cats extends Countable {/**/}
public class Humans extends Countable {/**/}
Then, you can instantiate any of your objects
Dogs dog = new Dogs("...");
Dogs dog2 = new Dogs("...");
Cats cat = new Cats("...");
Humans human = new Humans("...");
You can then get each total count by invoking the getTotalCount method from an instance:
System.out.println(dog.getTotalCount());
System.out.println(cat.getTotalCount());
System.out.println(human.getTotalCount());
Which will give you
2
1
1
Important Notes:
1) getTotalCount() is invoked via instances (non-static). This might be strange semantically, as you have a method returning a result for a total of instances, so any modification on this would be nice.
2) In order to allow the count on different types, map get & put operations are applied. Those operations have their own complexities and might be costly at cases. For more information on this, look in this answer.
Create a static field private static int humanCount = 0 and increment it in the constructor:
public class Humans {
private String mHumanName;
private static int humanCount = 0;
public Humans(String humanName) {
mHumanName = humanName;
humanCount++;
}
public String getHumanName() {
return mHumanName;
}
public static int populationCount() {
return humanCount;
}
}
You can add a finalize() method and use it to decrement the count. It will be called when the object is destroyed.
protected void finalize( ) throws Throwable {
humanCount--;
super.finalize();
}

Handling Static Collections in Java

say I have a class A which is as follows
public class A {
protected static float[] floatArray = null;
protected static Map<Integer, float[]> history = new HashMap<Integer,float[]>();
protected static Integer historyCount = 0;
public void runEverySecond(Populator objPopulator) {
floatArray = objPopulator.getValues();
history.put(historyCount, floatArray);
historyCount++;
}
}
and Class B looks as follows
public class B {
private A objA;
protected final static Populator objPopulator = new Populator();
public void run(Integer numOfTime) {
for(int i = 0; i < numOfTime; i++)
objA.runEverySecond(objPopulator);
}
}
and Class Populator looks as follows
public class Populator {
protected float[] randomValues = new float[2];
public float[] getValues() {
randomValues[0] = //some new random float value generated for every call
randomValues[1] = //some new random float value generated for every call
return randomValues;
}
}
and class containing main looks as follows
public class MainClass {
public static void main() {
final B objB = new B();
objB.run(10);
}
}
Here is the problem I am facing, the Map history contains the same value for every entry in the map. I want the Map history to store all the values generated by objPopulator.getValues() method. How do I do it?
Some help would be really appreciable.
Thanks in Advance :)
The Actual code (with irrelevant code removed ) represented by class A
public class MySuperAgent implements Agent {
protected static float[] marioFloatPos = null;
protected static Map<Integer, float[]> levelRecord = new HashMap<Integer, float[]>();
protected static Integer mapCount = 0;
/* protected static int testCount = 0;
protected static float[] testx = new float[2];
protected static float[] testy = new float[2];*/
#Override
public void integrateObservation(Environment environment) {
marioFloatPos = environment.getMarioFloatPos();
levelRecord.put(mapCount, marioFloatPos);
mapCount++;
/*if(testCount < 2){
testx[testCount] = marioFloatPos[0];
testy[testCount] = marioFloatPos[1];
testCount++;
} else {
testCount = 0;
}*/
}
}
class C represent environment object
integrateObservation method is called from class similar to class B
if I use the code within the comment block then I am able to record only 2 past values of x and y of Mario. I need a way to store all the values of x and y of Mario :)
Every entry in your Map has a reference to the same static field floatArray as its value.
Instead of having floatArray as a static member variable in A consider:
public void runEverySecond(Populator objPopulator) {
float[] floatArray = objPopulator.getValues();
history.put(historyCount, floatArray);
historyCount++;
}
EDIT Also I don't know how your code for class A would compile as it is. Shouldn't runEverySecond take a Populator parameter instead of Object? See revised snippet above.
There's only one floatArray and you keep reassigning it.
This code was almost impossible to follow in a reasonable way--what a mess.

Categories

Resources