How to share common code across Java classes - java

I have those Java classes:
public class Item {
String name;
int price;
int weight;
public Item(String name, int price, int weight) {
this.name = name;
this.price = price;
this.weight = weight;
}
}
public class Sword extends Item {
int damage;
int speed;
public Sword(String name, int price, int weight, int damage, int speed) {
super(name, price, weight);
this.damage = damage;
this.speed = speed;
}
}
public class HasDurability {
int current_durability;
int max_durability;
public HasDurability(int durability) {
this.max_durability = durability;
this.current_durability = durability;
}
public void damage(int damage) {
current_durability -= damage;
}
}
I want to share code from HasDurability class with Sword but not with Item.
Edit: Also I want to share HasDurability with other classes like Armor.
I can only extend one class. How do I share code from Item and from HasDurability to Sword class?

Seems more like you should just have hierarchy like this
public class Item
public class DurableItem extends Item
public class Sword extends DurableItem
Unless there is something which can have durability that is not an item, which doesn't sound likely.

You can reuse code by either composition or inheritance. The first way is you instantiate a class you want to use the methods of in the "extending" class and you use it like that. The other way is you extend the class.
So either you do
Item item = new Item(name, price, weight);
HasDurability hasDurability = new HasDurability(durability);
in the class you want those classes to be used, or you extend a common superclass.
You could create an abstract superclass and provide shared methods if the need arises.
I also recommend you rename the HasDurability class to just Durability, because the "hasSomething" or "isSomething" is usually used for boolean values like:
boolean hasFur = false;// imagine you have an animal class and you wanna know if the animal has fur or not

Related

Is it safe to assign default values to class members in Java?

Here's are two classes, Passenger and Car. Instead of initializing all private members of the Car class in all constructors, I thought of setting default values for them and overwriting specific members' values if provided by the instance creator.
import java.util.ArrayList;
class Passenger {
private String name;
Passenger(String name) {
this.name = name;
}
}
class Car {
private String color = "red";
private int numberOfWheels = 4;
private ArrayList<Passenger> passengers = new ArrayList<Passenger>();
Car() {}
Car(String color) {
this.color = color;
}
Car(int numberOfWheels) {
this.numberOfWheels = numberOfWheels;
}
public void addPassenger(Passenger p) {
this.passengers.add(p);
}
}
Is it safe to set default values to class members like this? Any pitfalls to avoid for any particular data types (even other than the ones I have used)?
Yes, it is safe.
Personally I prefer initialize where is declaration if is a common value for all constructors. If I have more constructor is not very pleasure to write that thing multiple times. And for me is more clear what value have.

Working with enum types in java

I need to create a "super" enum (here ESideItem) which will keep record of "sub" enums (SALAD, FRY, TACO) & I need to access "sub" enum's fields(price) from outside too.
I meant "super" as main type & "sub" as sub-type of that main type.
There can be many types of SideItems (FRY, SALAD, TACO) for a meal & each of these sideitems can be of many types (i.e SALAD can be CHICKEN or AFGHAN or MIMOSA etc).
Following Ray Tayek's answer to this question I've implemented this:
public abstract class SideItem {
public enum FRY {
FRENCHFRY(25.25f), SEASONEDCURLYFRY(30.10f);
private float price;
FRY(float price) {
this.price = price;
}
public float getPrice() {
return price;
}
}
public enum SALAD{
AFGHANSALAD(50.25f), CHICKENSALAD(40.10f), MIMOSASALAD(45.89f);
private float price;
SALAD(float price) {
this.price = price;
}
public float getPrice() {
return price;
}
}
public enum TACO{
MONSTERTACO(26.25f), NACHOMONSTERTACO(35.10f);
private float price;
TACO(float price) {
this.price = price;
}
public float getPrice() {
return price;
}
}
public enum ESideItem {
FRY(SideItem.FRY.FRENCHFRY), SALAD(SideItem.SALAD.AFGHANSALAD), TACO(SideItem.TACO.MONSTERTACO);
ESideItem(Enum e) {
this.e = e;
}
public Object[] subValues() {
return e.getDeclaringClass().getEnumConstants();
}
final Enum e;
}
}
I implementd Main.java as follows:
public class Main {
public static void main(String[] args) {
for(SideItem.ESideItem aSideItem : SideItem.ESideItem.values()){
System.out.println(aSideItem);
for(Object o : aSideItem.subValues()){
System.out.format("%-15s",o);
System.out.println();
}
System.out.println();
}
}
}
The output is:
FRY
FRENCHFRY
SEASONEDCURLYFRY
SALAD
AFGHANSALAD
CHICKENSALAD
MIMOSASALAD
TACO
MONSTERTACO
NACHOMONSTERTACO
Main.java is like client side & SideItem.java is like server side. I can change or add any instance in the ESubItem enum from SideItem.java. Main.java should give output according to that change
But I do need to get price of these individual TACO's, SALAD's, FRY's . Is there any way to access these fields from Main.java using enum?
If not then what kind of data structure should I use to solve this problem ?
You should be using an interface:
interface Food
{
float getPrice();
}
public enum Fry implements Food
{
FRENCH_FRY(25.25f), SEASONED_CURLY_FRY(30.10f);
private final float price;
FRY(float price) {
this.price = price;
}
#Override
public float getPrice() {
return price;
}
}
And the same for the other two...
Then you can compose them like so:
public enum Meal implements Food {
HAPPY_MEAL(Fry.FRENCH_FRY, Fry.SEASONED_CURLY_FRY),
SAD_MEAL(Salad.AFGHAN_SALAD);
private final List<Food> items;
Meal (Food... items) {
this.items = Arrays.asList(food);
}
#Override
public float getPrice()
{
return (float) items.stream().mapToDouble(Food::getPrice).sum();
}
}
If you want to access the price for calculations etc. the easiest way is to make all those enums implement an interface with public float getPrice().
For display purposes you would only need to modify the toString() of each enum.
The enum ESideItem and SideItem classes seem unnecessary though. Especially the ESideItem doesn't seem like it should be an enum at all, and the way you're using getDeclaringClass().getEnumConstants() is just a really bad idea.
You will need to something like:
for(Object o : aSideItem.subValues()){
if(o instanceof SideItem.FRY)
((SideItem.FRY)o).getPrice()
You can define an interface, say
public interface Priced {
double getPrice();
}
The enums can implement that
public enum FRY implements Priced { // no further change needed, method already there
and you can return an array of Priced with your subValues().
public Priced[] subValues() {
return Stream.of(FRY.values(), SALAD.values(), TACO.values()).
toArray(Priced[]::new);
}
I'm not entirely sure if the latter works this way, but being able to implement an interface in your enum is the main point.

Chaining multiple constructors

I understand that when chaining constructors this must be done on the first line of the main constructor, can someone explain how you would go about the below code.
I want to chain to all constructors so that they can all be private other than the main constructor.
public class Flight {
int passengers = 0;
int seats = 150;
double maxKgPerPassenger;
private Flight(int passengers) {
this.passengers = passengers;
}
private Flight(int seats) {
this.seats = seats;
}
private Flight(double maxKgPerPassenger) {
this.maxKgPerPassenger = maxKgPerPassenger;
}
public Flight(int passengers, int seats, double maxKgPerPassenger) {
this(passengers);
this(seats);
this(maxKgPerPassenger);
}
}
A constructor is up to set as many fields as possible or construct an instance completely.
You pick a constructor which has a greater number of arguments and use it within constructors with a smaller amount. For example,
public Flight(double maxKgPerPassenger) {
this(0, 0, maxKgPerPassenger); // default, default, maxKgPerPassenger
}
private Flight(int passengers, int seats, double maxKgPerPassenger) {
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
I want to chain to all constructors so that they can all be private other than the main constructor.
I suggest the opposite way. Make all constructors you are going to use public, but an all-arguments constructor private if you won't be using that.
The approach you tried to adopt is similar to the builder pattern where each method sets a single field. You definitely need to have a look at it if a number of arguments are going to grow up.
Why do you want to chain constructors ?
As you chain constructors, you have to specify some default values from the constructor with less argument to the invoked constructor with more arguments.
You do the reverse here :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this(passengers);
this(seats);
this(maxKgPerPassenger);
}
You indeed want to invoke from the constructor with the most argument all other constructors.
It makes no sense and it is not valid either as a constructor can invoke a single other constructor of the same class.
I want to chain to all constructors so that they can all be private
other than the main constructor.
Things work in the reverse order.
The actual code doesn't seem to need constructor chaining.
This one is enough :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
Suppose that class clients could create Flight instances with two flavors :
by passing all parameters
by passing only the seats parameter (remains being valued with default values)
You could so write :
public Flight(int passengers, int seats, double maxKgPerPassenger){
this.passengers = passengers;
this.seats = seats;
this.maxKgPerPassenger = maxKgPerPassenger;
}
public Flight(int seats){
super(50, seats, 10); // you pass some default values for passengers and maxKgPerPassenger
}
make the default constructor private to prevent constructor instantiation and instantiate objects using a public static method. This way you can work around the constructor restriction. To add a little confusion I converted your constructors to normal methods using the class name by adding void return type. Also consider if want you really want isn't the Builder pattern.
public class Flight {
private int passengers = 0;
private int seats = 150;
private double maxKgPerPassenger;
private Flight() {}
private void Flight(int passengers)
{
this.passengers = passengers;
}
private void Flight(int seats)
{
this.seats = seats;
}
private void Flight(double maxKgPerPassenger)
{
this.maxKgPerPassenger = maxKgPerPassenger;
}
public static Flight create(int passengers, int seats, double maxKgPerPassenger)
{
Flight flight = new Flight();
flight.Flight(passengers);
flight.Flight(seats);
flight.Flight(maxKgPerPassenger);
return flight;
}
}

How to convert an object from class to superclass

I have to model breakwater that controls permissions in certain coast. My solution implements a class "Ship" and classes "OilShip", "FishingShip" and "CarriageShip", I used inheritance and made
public class OilShip extends Ship{
...
}
public class FishingShip extends Ship{
...
}
public class CarriageShip extends Ship{
...
}
In another class I have Ship ship=new Ship(...); and I'd like to somehow make an Oilship into Ship, i.e.
public Class Abcd{
Ship ship;
public Abcd(OilShip oship){
ship=oship; //*************
}
}
There seems to be a problem with the code, please tell me.
Make sure you call the superclass' constructor inside your subclasses' constructors.
This solution works fine for me:
public class Ship {
private String name;
private int weight;
public Ship(String name, int weight) {
this.name = name;
this.weight = weight;
}
}
class OilShip extends Ship {
private int oilCapacity;
public OilShip(int oilCapacity, String name, int weight) {
super(name, weight);
this.oilCapacity = oilCapacity;
}
}
class FishingShip extends Ship {
private int fisherMen;
public FishingShip(int fisherMen, String name, int weight) {
super(name, weight);
this.fisherMen = fisherMen;
}
}
class CarriageShip extends Ship {
private int containers;
public CarriageShip(int containers, String name, int weight) {
super(name, weight);
this.containers = containers;
}
}
As mentioned before, Java-classes should always be given a name, where the first character is in UPPERCASE and the same with each new word --> CamelCase
You don't need different constructors. The awesome thing behind using inheritance here, is, that no matter what subclass from the superclass "Ship" you put into your constructor in "abcd", it will be accepted:
public class Abcd {
private Ship ship;
public Abcd(Ship ship){
this.ship = ship;
}
}

How to extend or implement classes? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Picture to show task:
First I am sorry, for my bad to for expressing my mind.
I have such a task, I don't need that you do it for me.
Vehicle is parent class for Sedan (Cause Sedan class is String type).
How to extend or implement Vehicle class with universal class?
I forgot to ask my teacher, but maybe you will know, what means striped pointer to Owner class, and what is that: has a?
P.S. If you need code that I have written already, I will show you.
So this is my parent Vehicle class:
public class Vehicle {
private int vehicleNumber;
protected int fuelTankSize;
protected int maxSpeed;
protected Owner owner;
//1
public Vehicle(int vehicleNumber){
this.vehicleNumber = vehicleNumber;
}
//2
public Vehicle(int vehicleNumber, int fuelTankSize) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
}
//3
public Vehicle(int vehicleNumber, int fuelTankSize, int maxSpeed) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
this.maxSpeed = maxSpeed;
}
//4
public Vehicle(int vehicleNumber, int fuelTankSize, int maxSpeed, Owner owner) {
this.vehicleNumber = vehicleNumber;
this.fuelTankSize = fuelTankSize;
this.maxSpeed = maxSpeed;
this.owner = owner;
}
//1
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed (int maxSpeed){
this.maxSpeed = maxSpeed;
}
//2
protected int getFuelTankSize(){
return fuelTankSize;
}
protected void setFuelTankSize (int fuelTankSize){
this.fuelTankSize = fuelTankSize;
}
//3
public Owner getOwner(){
return owner;
}
public void setOwner (Owner owner){
this.owner = owner;
}
}
child Sedan with:
public class Sedan extends Vehicle {
private String registrationIndex;{
}
public Sedan (int vehicleNumber, int fuelTankSize, int maxSpeed, String registrationIndex, Owner owner) {
super(vehicleNumber, fuelTankSize, maxSpeed, owner);
this.setRegistrationIndex (registrationIndex);
}
public String getRegistrationIndex (){
return registrationIndex;
}
public void setRegistrationIndex (String registrationIndex) {
this.registrationIndex = registrationIndex;
}
}
second Universal child without an error:
public class Universal extends Vehicle {
private int trunkSize;
public Universal (int vehicleNumber, int fuelTankSize, int maxSpeed, int trunkSize, Owner owner) {
super(vehicleNumber, fuelTankSize, maxSpeed, owner);
this.setTrunkSize (trunkSize);
}
public int getTrunkSize() {
return trunkSize;
}
public void setTrunkSize(int trunkSize) {
this.trunkSize = trunkSize;
}
public void printDescription() {
super.printDescription();
System.out.println("Universalo bagažinės tūris: " + getTrunkSize() + "l.");
}
}
and some misterious (to me) Owner class:
public class Owner {
public String firstName;
public String lastName;
public Owner (String firstName){
this.firstName = firstName;
}
public Owner (String firstName, String lastName){
this.firstName = firstName;
this.lastName = lastName;
}
}
added VechileTest for testing:
public class VehicleTest {
public static void main(String[] args) {
Vehicle vehicleInf = new Vehicle (1, 45, 260);
Universal universalInf = new Universal(2, 50, 220, 70);
Sedan sedanInf = new Sedan (3, 40, 180, "AVA 123");
vehicleInf.printDescription();
universalInf.printDescription();
sedanInf.printDescription();
}
}
Well, 1st of all I recommend you read a good tutorial / explanation of UML class diagrams, like this here for example.
After you know the basics, it should be easy to translate that into Java code.
I'll give you the code for the Universal class and a start for your Vehicle. The rest you'll have to do on your own.
The class Universal:
public class Universal extends Vehicle {
private int trunkSize;
public int getTrunkSize() {
return this.trunkSize;
}
public void setTrunkSize(int trunkSize) {
this.trunkSize = trunkSize;
}
}
As you can see the first block inside a class box refers to the variables. The - and + indicates the visibility (private for -, public for +).
The next block is about the methods, specifying visibility, return type, method name and parameters (type and name).
The arrow between Universal and Vehicle indicates a inheritance relationship (see in code that Universal extends Vehicle).
So all in all the diagram is a construction plan for your classes; at least for the static part, meaning the relationships and state they can have.
The start of class Vehicle:
public class Vehicle {
private int vehicleNumber;
// the rest here ...
}
Edit:
Well, now that I see your code, you seem to have a few misconceptions:
The Sedan type is not from type String, it is from type Sedan (which extends Vehicle). Just the new member variable in the Sedan type is of type String, does not matter.
To your 1st question: The Vehicle class is the base (parent) class of Sedan. You do not to do anything with it, inheritance is expressed from the child towards the parent, not the other way around. Vehicle should usually be declared abstract (as you cannot create an instance of a generic Vehicle), but this is not in the diagram.
To your 2nd question: The has a relationship is just this. It expressed that one class has another class as it's member (which is redundantely expressed inside the class diagram already), so nothing to do for that.
Additionally your code has a few issues:
I do not see any constructors declared in Vehicle class, those 4 can go.
Your Sedan has a superflous pair of {} after declaration of your registrationIndex variable.
Since your Vehicle has no default constructor, you must call this constructor from your Sedan class (or remove the constructors from Vehicle.
Your Universal class calls the Vehicle constructor with the trunkSize while the Vehicle constructor expects the vehicleNumber there.
Your Vehicle class doesn't have a parameterless constructor, which means that Universal and Sedan must explicitly call one of them (super(...);). You're doing this in Universal (albeit incorrectly as you're passing the trunk size instead of the vehicle number expected by Vehicle's constructor) but not in Sedan.
As for the second question: The two major relations in OOP are is a and has a. The difference can be easily explained like this:
A Sedan is a vehicle
A vehicle has an owner
is a means it inherits some properties of something else, has a means that it has a reference to something else.

Categories