Temporary extending existing object in Java - is this a good idea? - java

I'm implementing an algorithm during which we must temporary order existing objects (we will compare them according to this order during execution of the algorithm). I'm thinking of the best way of doing that, while being consistent with OOP paradigm.
So let's think about the following example. We have objects of class Car, and now we want to use the algorithm on such objects. So I thought of making a subclass OrderedCar, which will have a unique int in its fields. This class would have a function - ArrayList<OrderedCar> defineOrder(ArrayList<Car> order), which would output OrderedCar list with numbers corresponding to the indices of a given car in order table. We would then be able to compare OrderedCars using numbers with which they were initialized. We could then execute the algorithm on OrderedCars and convert them to Cars after the algorithm terminates.
During the algorithm I need all of the methods from Car class, that's why I thought of making OrderedCar a subclass. Is this a good idea though? Also, how to create a constructor in Java, which will "copy" the Car and assign a number to it (I'm thinking of something like public OrderedCar(Car c, int order), but what to do with the car c in order to "copy" it? I don't want to copy all of the fields individually, is there some kind of shortcut in Java?)

You could favor composition over inheritance and just create a class that contains a Car and its order:
public class OrderedCar{
private int order;
private Car car;
public OrderedCar(int order, Car car){
this.order = order;
this.car = car;
}
public int getOrder(){
return order;
}
public Car getCar(){
return car;
}
}
Then you can sort this class by its order, and whenever you needed to operate on its car, you would just call the getCar() function.

If it is enough for you to compute the order basing on public methods of your Car class I think the simplest solution would be to just implement a comparator.
Here is a small example. I'm using the age property to do the sorting.
public class Car {
protected int age;
protected String manufacturer;
Car(int age, String manufacturer) {
this.age = age;
this.manufacturer = manufacturer;
}
public int getAge() {
return age;
}
public String toString() {
return this.manufacturer + " age: " + this.age;
}
}
import java.util.Comparator;
public class CarComparator implements Comparator<Car> {
public int compare(Car c1, Car c2) {
// do some complicated comparison using
// Car public methods, we simple use to
// age property here
return c1.getAge() - c2.getAge();
}
}
import java.util.ArrayList;
public class CarComparingApp {
public static void main(String[] args) {
Car ferrari = new Car(1, "Ferrari");
Car maserati = new Car(4, "Maserati");
Car subaru = new Car(3, "Subaru");
ArrayList<Car> cars = new ArrayList<Car>();
cars.add(ferrari);
cars.add(maserati);
cars.add(subaru);
cars.sort(new CarComparator());
for(Car c: cars) {
System.out.println(c);
}
}
}

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;
}

Generate different object with same attributes

I am building a project. One of the requirements is to generate the object with the same attributes but randomly different values. I tried to use deep-copy, but not sure if it is conceptually correct.
So, for example, I have a Person class, inherited from the abstract class Character.
And there is a ScenarioGenerator, which I'll put the getRandomPerson method to create the instances of the Person class.
Any help of advice is highly appreciated.
Here is part of my Person class:
public class Person extends Character {
private Random random;
private boolean pregnant;
private boolean isYou;
Person(int age, Profession profession ,Gender gender, BodyType bodyType, boolean isPregnant) {
super(age, gender, bodyType);//pass the attributes to the super class called Character
}
Person (Person otherPerson) { //copy constructor
this.age = otherPerson.getAge();
this.gender = otherPerson.getGender();
this.bodyType = otherPerson.getBodyType();
}
public Profession getProfession () { // One of the getters which generate random enum value
//only adults have profession
if (getAge()<=16 || getAge()>68) {
return Profession.NONE;
} else {
return Profession.values()[new Random().nextInt(Profession.values().length)];
}
}
// setters and getters
}
And the method of my ScernarioGenerator class:
public class ScenarioGenerator {
public Person getRandomPerson() {
//need age, gender, bodyType, profession, pregnancy
Person people = new Person(person.getAge(), person.getProfession(), person.getGender(), person.getBodyType(), person.isPregnant());
Person clone = new Person(people);
return clone;
}
If you want a deeply cloned object then you can get it by implementing the clone class and overriding the clone function like
public class Person extends Character implements Cloneable {......}
Then you may simply get the new deep copied object by
Person clone=(Person) people.clone();

Can you change a immutable class?

This is a theoretical question for practice.
The question is
Create an immutable class Car.
Create some instances of car to fill an Arraylist<Car> inside a Garage class.
The MyGarage class implements these methods from Garage:
getCar(String reg) – search for the car with registration number reg.
getMake(String make) – returns a list of cars that match the given make.
totalValue() – calculates the total value of all cars in the list.
changeOwner(String reg, String ow) – change the owner of car that has registration number reg to ow.
I do not understand the changeOwner method as it is not suppose to be able to change a instances of a immutable class I thought???
This is what I have done to work around it but just seems silly
import java.util.ArrayList;
public class MyGarage implements Garage {
private ArrayList<Car> myGarage;
public MyGarage() {
myGarage = new ArrayList<Car>();
}
#Override
//Adds a Car if the registration is unique
public boolean add(Car c) {
for(Car car : myGarage) {
if(car.getRegistration().equals(c.getRegistration())) {
System.out.println("Car has the same Registration as another illegal");
return false;
}
}
myGarage.add(new Car(c.getOwner(),c.getRegistration(),c.getMake(),c.getkilometres(), c.getprice()));
return true;
}
#Override
public Car getCar(String carID) {
for(Car car : myGarage) {
if(carID.equals(car.getRegistration())) {
System.out.println("Car Found");
return car;
}
}
System.out.println("No car of that record");
return null;
}
#Override
public ArrayList<Car> getMake(String make) {
ArrayList<Car> carModel = new ArrayList<Car>();
for(Car car : myGarage) {
if (car.getMake().equals(make)) {
carModel.add(car);
}
}
System.out.println(carModel.toString());
return carModel;
}
#Override
public void totalValue() {
double amount = 0;
for(Car car : myGarage) {
amount = car.getprice() + amount;
}
System.out.println("The total amount is: " + amount);
}
#Override
public boolean changeOwner(String registration, String ow) {
for(Car car : myGarage) {
if(car.getRegistration().equals(registration)) {
myGarage.remove(car);
car = new Car(ow, "444","F-50", 4, 4000.99);
myGarage.add(car);
return true;
}
}
return false;
}
}
In object-oriented and functional programming, an immutable object
(unchangeable object) is an object whose state cannot be modified
after it is created. This is in contrast to a mutable object
(changeable object), which can be modified after it is created. In
some cases, an object is considered immutable even if some internally
used attributes change, but the object's state appears unchanging from
an external point of view. - WikiPedia
Immutable objects are thus instances whose state doesn’t change after they have been initialized. These types of classes are generally good for applications that need to implement some form of caching and where you are worried about thread-safety in a multi-threaded environment (immutable objects are inherently thread-safe).
I don't see your Car class, but assuming it'll look something like this:
public final class Car {
final String registration;
final String owner;
public Car(String registration, String owner) {
this.registration = registration;
this.owner= owner;
}
public String getRegistration() {
return registration;
}
public String getOwner() {
return owner;
}
}
... notice that there are no setter methods in this class. Hence a car can only be initialized (i.e Car myCar = new Car("abcd", "John"); and the variables in them (namely, registration and owner) can never be updated.
So your changeOwner method is essentially looping through the instances of car in your garage and when it finds a matching registration number it removes that instance of car from your garage and then adds a whole new one.
To demonstrate this, you can run the following:
public class Garage {
public static void main(String ... args) {
List<Car> myGarage = new ArrayList<>();
myGarage.add(new Car("CG404GH", "John"));
System.out.println(myGarage);
for(Car car : myGarage) {
if("CG404GH".equals(car.getRegistration())) {
myGarage.remove(car);
Car updateCar = new Car("DD404GH", "John");
myGarage.add(updateCar);
}
}
System.out.println(myGarage);
}
}
This would print out something similar to the following (the portion after the # would be different on each run):
[Car#4411d970]
[Car#6442b0a6]
The important thing to notice here is that the value after the # are different, hence they are two completely different classes (instances) of car

modeling a inheritance hierarchy... java

Lodgings in Oshkosh can be classified into three kinds – Hotels (modeled by the number of rooms and star rating), Hostels (modeled by the number of rooms and whether bike rentals are available), and Bed-n-Breakfasts (modeled by the number of rooms and whether late arrivals are allowed). Rates per room per night are always fixed and cost $40, $20 and $55 for Hotels, Hostels and Bed-n-Breakfasts respectively.The skeleton code for an inheritance hierarchy that models this scenario is stubbed out below. Complete all missing parts so that the code compiles, models the inheritance hierarchy, and has all the functionality described above. You should decide which classes the appropriate data members are stored in, and the types of those data members. In every class, complete theconstructor and provide a method, computeRate,which takes as parameter the number of nights spent and returns the total room rate for that lodging.No other methods should be provided.
Can someone give me some tips on weather you think I am going about this problem in the right way. the main thing that I am having issues with is the computeRate method. Im not sure how to set the prices of the Lodgings for hotels, Bed-n-Breakfasts, and hostels. I tried using super but im not completely sure if thats what I am supposed to do.
// parent class
public class Lodging
{
int sum;
int price;
public Lodging( int price ) {
this.price = price;
}
}
public double computeRate(int numberOfNights){
price *= numberOfNights;
return sum;
}
// child class
public class Hostel extends Lodging
{
private int numberOfRooms;
private boolean bikeRentals;
public Hostel( int rooms, boolean rentals) {
super(20);
this.numberOfRooms = rooms;
this.bikeRentals = rentals;
}
}
// child class
public class Hotel extends Lodging
{
private int rooms;
private int starRating;
public Hotel( int rooms, int starRating ) {
super(40);
this.rooms = rooms;
this.starRating = starRating;
}
}
// child class
public class BednBreakfast extends Lodging
{
private int numberOfRooms;
private boolean lateArrivals;
public BednBreakfast( int rooms, boolean late ){
super(55);
this.numberOfRooms = rooms;
this.late = late;
here is the given skeleton code
class Lodging
{
public Lodging( )
{
}
}//End class Lodging
class Hotel
{
public Hotel( )
{
}
}//End class Hotel
class Hostel
{
public Hostel( )
{
}
}//End class Hostel
class BednBreakfast
{
public BednBreakfast ( )
{
}
}//End class BednBreakfast
Each of your classes has rooms, so I would move that to the parent class, and add it to the constructor.
Also, a Lodging is an abstract concept, so you cannot make a new Lodging(), you need a specific instance of one.
public abstract class Lodging {
private double nightlyRate;
private int capacity;
public Lodging( int capacity, double rate ) {
nightlyRate = rate;
this.capacity = capacity;
}
public double computeRate(int numberOfNights){
return this.nightlyRate * numberOfNights;
}
}
Then, there's nothing wrong with super(rooms, 20), for the Hostel example. It's correctly setting up the parent class's fields, and each subclass will inherit the super class's computeRate() method. The problem description doesn't indicate it needs to be overriden.

Using the Comparable interface when comparing Strings

I searched for this question, but I only found one thread that was kind of confusing, so I'm going to ask here for what I hope will be a clearer answer.
I have an assignment to use the Comparable interface to sort objects in an array by customer name. I have only done this with integers so far, so I'm not sure how to compare the strings together. How would I go about that? Here is where I am so far, assuming I am to use a.name compared to this.name:
public int comparedTo(Customer a)
{
} //end comparedTo
I also need to make a class to implement the Comparator interface to sort the values based on customer purchases and I think I did that properly, but I'd like to make sure before I go ripping my hair out when it's wrong. Here is what I did for that:
class NameComparator implements Comparator{
public int compare(Object cust1, Object cust2){
String cust1Purch = ((Customer)cust1).purchase;
String cust2Purch = ((Customer)cust2).purchase;
return cust1Purch.compareTo(cust2Purch);
}
Any help is greatly appreciated!
Its all ok, but you can specify Comparator generic type and then no need to cast objects:
class NameComparator implements Comparator<Customer>{
public int compare(Customer cust1, Customer cust2){
String cust1Purch = cust1.purchase;
String cust2Purch = cust2.purchase;
return cust1Purch.compareTo(cust2Purch);
}
Here is a complete example that might help you:
A CustomerComparator:
class CustomerComparator implements Comparator<Customer> {
#Override
public int compare(Customer c1, Customer c2) {
return c1.name.compareTo(c2.name); // or, simply c1.compareTo(c2);
}
}
A Comparable Customer:
class Customer implements Comparable<Customer> {
String name;
public Customer(String name) {
this.name = name;
}
#Override
public int compareTo(Customer o) {
return name.compareTo(o.name);
}
public String toString() {
return name;
}
}
A simple test driver:
public class Test {
public static void main(String[] args) {
List<Customer> customers = Arrays.asList(new Customer("Bravo"),
new Customer("Charlie"),
new Customer("Delta"),
new Customer("Alpha"));
Collections.sort(customers);
// Or
// Collections.sort(customers, new CustomerComparator());
System.out.println(customers);
}
}
(ideone.com demo)
Looks fine. But you can utilize Generics:
class NameComparator implements Comparator<Customer> {
public int compare(Customer cust1, Customer cust2) {..}
}
I seem to get it right for the Comparable interface. Nothing really complicated there.
As for the Comparator, if you're not using generics, you also need to validate both argument for the same base type, at least Comparable since you're using that interface :
if (cust1 instanceof Comparable && cust2 instanceof Comparable) {
Comparable c1 = (Comparable) cust1;
Comparable c2 = (Comparable) cust2;
return c1.compareTo(c2);
} else {
return false;
}
1) I would use generics to define your comparator and avoid additinal class casting:
class NameComparator implements Comparator<Customer> {
public int compare(Customer cust1, Customer cust2) {
...
}
}
2) String class in java already implements Comparable interface ( http://download.oracle.com/javase/1.5.0/docs/api/java/lang/String.html ). So, if you need to just compare on customer's name or purchase string, then you can just delegate it to String and that's what you already do.

Categories

Resources