Reach parent class methods from arraylist of subclasses - java

I am trying to reach my parent class Car() variables and methods, from my ArrayList in main() of Objects Automobile(), Bus() which all inherit Car(). It gives me the opportunity to get the .Class and I know I can then compare if the class is Automobile or Bus and then do some operations, but I am actually trying to sort allInOne() ArrayList by getModel() Strings.
public class Car {
private String brand;
private String model;
public String getBrand(){
return brand;
}
public String getModel(){
return model;
}
}
public class Automobile extends Car {
int x;
Automobile(String brand, String model, int x){
super(brand, model);
this.x = x;
}
}
public class Bus extends Car {
int x;
Bus(String brand, String model, int x){
super(brand, model);
this.x = x;
}
main(){
Car first = new Automobile("brand1", "model1", 2);
Car second = new Bus("brand2", "model2", 3);
ArrayList<Object> allInOne = new ArrayList<Object>();
allInOne.add(first);
allInOne.add(second);
//here is the question part
allInOne.get(0).getBrand;
}

Instead of having Object List use ArrayList<Car>
ArrayList<Car> allInOne = new ArrayList<>();
then you can access all these methods:
allInOne.get(0).getBrand();
OR
If you want to stick to List of Object for some reason, then you can do this:
((Car) allInOne.get(0)).getBrand();

When instantiating the List, change Car as reference type instead of Object so that you might use the methods/attributes inherited from Parent Class.
ArrayList<Car> allInOne = new ArrayList<Car>(); // Java 7
ArrayList<Car> allInOne = new ArrayList<>(); // Java 8 it is not longer necessary to put reference type when instance an object.

Related

Accessing properties of Generic class in Java

Hi I am new to Java Generics and I am trying to access properties inside generic class. So far I have found C# related answers, it would be of great help if someone could please guide as to how I should do it in java.
Say I have Class Car and it has properties integer type wheels and String type model.
Now I have a method say vehiclehelper(List<T> vehicles) which takes a generic type list.
At place of invocation of vehiclehelper, it will be like :
List<Car> cars = new ArrayList<>();
cars.add(new Car(4, "Honda"));
vehiclehelper(cars);
Now coming to vehiclehelpermethod, in its body I want to loop over the list<T>vehicles and fetch the wheels property from it..something like:
for(T vehicle: vehicles)
count+ = vehicle.getWheels();
Now here at this point I am getting error, saying property isn't defined. What should I do to fetch the wheel property from my list of generic type?
create an interface ICar or an abstract class that represents a car, and has the methods that you expect a car to have, (e.g getWheels()).
then send a list of the objects that implements/extend this class as a parameter carHelper(List<ICar> cars)
Your class Car is not generalized. It's common class. You just manipulate Car objects via generalized List collection. It should not any issues with access to Car fields through getters or setters if that fields are private. Code below works perfectly.
public class App {
public static void main(String[] args) {
List<Car> carList = new ArrayList<>();
carList.add(new Car(4, "Honda"));
carList.add(new Car(3, "Polaris Slingshot"));
System.out.println(carHelper(carList)); // the result is 7
}
static int carHelper(List<Car> cars) {
int count = 0;
for (Car car : cars) {
count += car.getWheel();
}
return count;
}
}
class Car {
private int wheels;
private String name;
public Car(int wheels, String name) {
this.wheels = wheels;
this.name = name;
}
public int getWheels() {
return wheels;
}
public void setWheels(int wheels) {
this.wheels = wheels;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
If you want to have universal method carHelper for any object type, then you have to make it generalized:
static <T> int carHelper(List<T> elements) {
int count = 0;
for (T element : elements) {
count += element.getWheel();
}
return count;
}
But in the case you will get compile-time error at element.getWheel() because T type is some unknown type. Compiler does not know about his methods. To find some generic solution we have to define boundary for method parameters. Let's say input parameters will be Vehicle or it's children. In Vehicle class, let's say, we will introduce needed fields and his descendants will inherit them. In the case below listed method will work. Read about wildcards in generics.
static int carHelper(List<? extends Car> elements) {
int count = 0;
for (Car element : elements) {
count += element.getWheels();
}
return count;
}

Instantiate objects using a helper class

I want to create an instance of my object, car. The problem I have is that i can create an instance of the car object such as, Car car1 = new car("Audi","A4","BF10YMR"); however I want to create car objects through a helper class. How do I call this helper class in main so that is of type car and not of type carHelper?
The car object requires a random registration number to be created and this is created in the carHelper class. The object is returned.
public class Car implements Comparable<Car>
{
public class Car
{
private String make;
private String model;
private String registration;
public Car(String make, String model, String reg)
{
this.make= make;
this.model= model;
registration = reg;
}
}
public class carHelper
{
public car genCar()
{
String reg = //some method to generate random registration.
String Make = //some method to randomly pick make from a list
String model = //some method to randomly pick model from a list
return new Car(make,model,registration);
}
}
public class Garage
{
public static void main (String args[])
{
Garage MyGarage = new Garage();
Car car1 = new Car("Audi","A4","BF10YMR") //works, but doesn't use helper
Car car2 = carHelper.genCar(); // something like this?
carHelper c = new carHelper(); // thought something like this but
System.out.println(c.genCar()); // creates object of type carHelper
// not car.
MyGarage.add(car1);
MyGarage.add(car2); // gives me carHelper cannot be converted to Car
}
}
public class GarageOp implements CarList
{
public GarageOp()
{
list = new ArrayList<Car>();
}
public boolean add(Car car)
{
if (list.contains(car) == false)
{
list.add(car);
return true;
}
}
}
Expected result is create car object using the helper class and add it to an ArrayList.
You could create this lists in the CarHelper and than, randomly, select the values and create a new Car with them. The UUID creates a random 128 bits (including hex) number and converts to a String
public class CarHelper {
private List<String> makeList = Arrays.asList("s", "t", "f", "n");
private List<String> modelList = Arrays.asList("yyt", "32g", "dc3", "aas");
public Car genCar() {
String reg = UUID.randomUUID().toString();
String make = makeList.get(new Random().nextInt(makeList.size() - 1));
String model = modelList.get(new Random().nextInt(modelList.size() - 1));
return new Car(make,model,reg);
}
}
Make the genCar() method as Static in the CarHelper class.
public car static genCar(){
// do stuff to create object
}
a non-static method can access a static variable or call a static method in Java.

Using reflection to get a specific attribute from a extended instance

I would like to make a generic method to get a List from the parameter object.
The problem is because I have a declared object with a instance of the other class that extends the declared class.
I don't want to use the instanceof solution because the number of classes that extends LimitedValue can be big.
I thought to use reflection for a solution, but I don't know how to use that with an instance of object, in this part of the code:
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
This is my full code:
public class CalculatorLimitedValue {
public static void main(String[] args) throws Exception {
StoreItem storeItem = new StoreItem(1L, "Name of StoreItem", 50L);
List listOfStoreItems = new ArrayList();
listOfStoreItems.add(storeItem);
LimitedValue limitedValue0 = new Store(listOfStoreItems);
List firstList = calculator(limitedValue0);
//do something with the list
SupermarketItem supermarketItem = new SupermarketItem(1L, "Name of SupermarketItem", 21L);
List listOfSupermarketItems = new ArrayList();
listOfSupermarketItems.add(supermarketItem);
LimitedValue limitedValue1 = new Supermarket(listOfSupermarketItems);
List secondList = calculator(limitedValue1);
//do something with the list
}
/** This is the method that I'd like to make generic to return a List */
private static List calculator(LimitedValue limitedValue) throws Exception{
Class cls = Class.forName(limitedValue.getClass().getName());
Object obj = cls.newInstance();
//This is wrong, I don't want a new instance.
Method[] methods = cls.getDeclaredMethods();
for(int x= 0; x < methods.length; x++) {
Method method = methods[x];
if ("java.util.List".equals(method.getReturnType().getName())) {
//How to get the value of this method from limitedValue instance ?
}
}
/* I don't want to use this one way, because my classes that extends LimitedValue
can be big. I would like to made a generic way to get de list of classes. */
if (limitedValue instanceof Store) {
System.out.println("This is a store");
return ((Store) limitedValue).getStoreItems();
} else if (limitedValue instanceof Supermarket) {
System.out.println("This is a supermarket");
return ((Supermarket) limitedValue).getSupermarketItems();
}
return null;
}
}
If it help, these are my other classes:
LimitedValue.class
public class LimitedValue { }
StoreItem.class
public class StoreItem {
private Long id;
private String nameOfStoreItem;
private Long valueOfStoreItem;
public StoreItem(Long id, String nameOfStoreItem, Long valueOfStoreItem){
this.id = id;
this.nameOfStoreItem = nameOfStoreItem;
this.valueOfStoreItem = valueOfStoreItem;
}
//getters and setters...
}
SupermarketItem.class
public class SupermarketItem {
private Long id;
private String nameOfSupermarketItem;
private Long valueOfSupermarketItem;
public SupermarketItem() {
}
public SupermarketItem(Long id, String nameOfSupermarketItem, Long valueOfSupermarketItem) {
this.id = id;
this.nameOfSupermarketItem = nameOfSupermarketItem;
this.valueOfSupermarketItem = valueOfSupermarketItem;
}
//getters and setters...
}
Store.class
public class Store extends LimitedValue {
private List<StoreItem> storeItems;
public Store(List<StoreItem> storeItems) {
this.storeItems = storeItems;
}
//getters and setters
}
Supermarket.class
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
//getters and setters
}
You could try to use reflection here to try to achieve what you want, but it would be better to reconsider your overall design and try to use a better object oriented design that solves the problem at hand.
In particular, lets say we consider adding a method called getItems to the LimitedValue class that returns a List of items, which may be SupermarketItems or may be StoreItems. If it is structured correctly, you won't need to know the actual type because the code will be abstracted over it polymorphically.
public abstract class LimitedValue {
List<? extends Item> getItems();
}
We've now defined a new method on LimitedValue, but we also have to consider that we've introduced this new Item thing. I note that the SupermarketItem and StoreItem all share similiar attributes, name, id and value, so it seems that it might be possible to use a single class to represent them all.
public abstract class Item {
final Long id;
final String name;
final Long value;
public Item(final Long id, final Long name, final Long value) {
this.id = id;
this.name = name;
this.value = value;
}
String getName() {
return name;
}
// other getters and setters
}
public class SupermarketItem extends Item {
public SupermarketItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
public class StoreItem extends Item {
public StoreItem(final Long id, final Long name, final Long value) {
super(id, name, value);
}
}
Now we've completely abstracted away the need for any reflection when accessing these objects - you can simply call item.getValue() as you will know that every item in the list is of type Item.
Of course, you'll also need to refactor the Store and SuperMarket classes, for example:
public class Supermarket extends LimitedValue {
private List<SupermarketItem> supermarketItems;
public Supermarket(List<SupermarketItem> supermarketItems) {
this.supermarketItems = supermarketItems;
}
public List<? extends Item> getItems() {
return supermarketItems;
}
}
and because you are only returning a List<Item> you always know what is in it, and you can change your main code to work with this.
This is a much cleaner long term solution.
To get the List value, use Method#invoke:
List list = method.invoke(limitedValue);
You don't need Object obj = cls.newInstance(); - you're not using it at all in the method.
In any case, you're making it very difficult for yourself. You could also define an interface
public interface HasList<E> {
List<E> getList();
}
and have all classes implement this.

Adding instance variables to objects using LinkedList Collection

I have a Car class :
public class Car {
public String name = null; // Name of the Car Model
public String color = null; // Color of the car
Car(){
/** DO WHATEVER***/
}
}
Then in the main() class I do this :
LinkedList<Car> myCars = new LinkedList<Car>();
myCars.add(new Car());
myCars.add(new Car());
myCars.add(new Car());
myCars.get(0).name = "Geep";
myCars.get(0).color = "Black";
myCars.get(1).name = "Camry";
myCars.get(1).color = "Red";
myCars.get(2).name = "Honda";
myCars.get(2).color = "Green";
My question :
Lets assume that at the time of Car object creations, we do not have values of these instance variables and we get them at a later stage, so that constructor initialization is not feasible.
Then is this the correct way above ? I mean how instance variables of each objects would be assigned values, in Java collection.I mean, using the get() method ? I understand, if we have lots of car
objects then we will use a for loop.
Please explain.
Thank you.
It would make more sense to change the constructor from: /** DO WHATEVER***/
to something like:
Car(String name, String color){
this.name = name;
this.color = color;
}
and later on to the insertion into the list:
myCars.add(new Car("Geep", "Black"));
myCars.add(new Car("Camry", "red"));
...
In case you don't have "the details" of the cars, and you simply need to instantiate a list with 50 cars and later on "add the details" - another question raises: where do the details come from ? if you don't know it in advance it has to come from an eternal source (user-input, file, etc) and then it would make sense to run in a loop over the list and add the details:
for (Car car : myCars) {
String name = ... // get the details of the car from an external source
String type = ... // get the details of the car from an external source
car.setName(name); // of course you'll have to implement setName() and setType()
car.setType(type); // which is a better practice than exposing the class members via public access
}
Regarding whether this is the correct way: I prefer overriding the constructor so that my initialization and setter code is at the same place.
Essentially, I would provide the constructor for Car as:
public class Car {
public String name = null; // Name of the Car Model
public String color = null; // Color of the car
public Car(String name, String color){
super();
this.name = name;
this.color = color;
}
}
I would then put it in my collection as:
LinkedList<Car> myCars = new LinkedList<Car>();
myCars.add(new Car("Jeep", "Black"));
myCars.add(new Car("Ferrari", "Red"));
First, it it not recommended to expose instance variables (public). Change public to private and create the getters. Also, you could create a constructor that takes a name and color in parameters:
public class Car {
private String name = null;
private String color = null;
public Car(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public String getColor() {
return color;
}
}
Then you can do :
LinkedList<Car> myCars = new LinkedList<Car>();
myCars.add(new Car("Jeep", "Black"));
myCars.add(new Car("Camry", "Red"));
myCars.add(new Car("Honda", "Green"));
There are many ways to do it but I would definitely set the car information before adding it to the list.

Storing multiple object types in a List

I have following homework about computer store:
There are several class include: Monitor, Case, Mouse, Keyboard.
All the classes have common fields: id, name, price, quantity.
Each class has some unique fields.
All most features are: add, update, delete, find, show list, save, load file
-So, first I will create a class named Product have 4 common fields. Above classes will extends from Product.
-Then, I think I maybe create a ComputerStore class which have a field is items type ArrayList. items stores all objects which are instance of 4 above classes But I'm not sure.
Whether it is reasonable? I need some ideas
Before , I always use ArrayList store for only one class like
List <String> list = new ArrayList<String>();
Now they are multi type. I think it's generic in Java, right??
In case, I want to update for 1 items. I must think about how to change information for them. Ex: mouse for some code, keyboard for another code. Anyway, thank for everybody!
Your approach is 100% reasonable.
You are completely on the right track with "generics". First, check out the official enter link description here.
Next, just think about your data in real world terms, like you are already doing: Monitor, case, mouse, and keyboard are products. Your computer store's inventory is a list of products.
Hint: A list of products.
Put that together with what you learn about generics through that tutorial, and you'll be good to go.
You could use java generic.First create a java collection (ex: List) with supper class type, Product. Now you could add any sub classes (Monitor , Keyboard etc) in your collection (List) that extends of class Product.
public class Product{
}
public class Monitor extends Product{
}
public class Keyboard extends Product{
}
List<Product> products = new ArrayList<Product>();
products.add(new Monitor());
products.add(new Keyboard());
Since you have a superclass (Product), you can have the list's type as Product, i.e.
List<Product> list = new ArrayList<Product>();
list.add(new Mouse());
list.add(new Keyboard());
It will allow you to iterate them and list their name and price without caring for the class, but if you intend to take an item out of the list you'll need to check its actual type (depending on what you do with it).
You can do like below
import java.util.List;
import java.util.ArrayList;
class Test{
public static void main(String... args){
List<MultiObj> multiObjs = new ArrayList();
MultiObj ob = new MultiObj(); multiObjs.add(ob);
ResX xOb = new ResX(); multiObjs.add(xOb);
ResY yOb = new ResY(); multiObjs.add(yOb);
ResZ zOb = new ResZ(); multiObjs.add(zOb);
for (int i = 0; i < multiObjs.size(); i++ ) {
System.out.println(multiObjs.get(i).getV());
}
System.out.println("Waoo its working");
}
}
class MultiObj{
public String greet(){
return "Hello World";
}
public String getV(){
return "Hello World";
}
}
class ResX extends MultiObj{
String x = "ResX";
public String getX(){
return x;
}
public String getV(){
return x;
}
}
class ResY extends MultiObj{
String y = "ResY";
public String getY(){
return y;
}
public String getV(){
return y;
}
}
class ResZ extends MultiObj{
String z = "ResZ";
public String getZ(){
return z;
}
public String getV(){
return z;
}
}
You could do this:
public class Item {
public Item(int id, string name, float price, int amount, int ArrayID) {
if (ArrayID == 1) {
ID1 = id;
name1 = name;
price1 = price;
amount1 = amount;
}
if (ArrayID == 2) {
ID2 = id;
name2 = name;
price2 = price;
amount2 = amount;
}
if (ArrayID == 3) {
ID3 = id;
name3 = name;
price3 = price;
amount3 = amount;
}
if (ArrayID == 4) {
ID4 = id;
name4 = name;
price4 = price;
amount4 = amount;
}
}
//ArrayID #1
public static int ID1;
public static String name1;
public static float price1;
public static int amount1;
//ArrayID #2
public static int ID2;
public static String name2;
public static float price2;
public static int amount2;
//ArrayID #3
public static int ID3;
public static String name3;
public static float price3;
public static int amount3;
//ArrayID #4
public static int ID4;
public static String name4;
public static float price4;
public static int amount4;
public static int[] id = ID1, ID2 ID3, ID4;
//so forth...
}

Categories

Resources