I would like to ask something about an issue i have.
Lets say we have an interface called Vehicle.
Then we have a class that implements this interface called Car.
Then another one called Bicycle.
Now the whole code uses these two objects (Car, Bicycle) and whenever needed interface Vehicle.
What if now i want to add a new attribute to Car class and due to this change also modify some of its methods. For example i can extend Car with a class called Car2. But now if i want to make use of Car2 in the code i will have to rewrite every single method and class that uses Car to a new class that will use Car2.
For example a method that does not belong to Car class.
int checkSpeed(Car c) {
speed = c.attributeX * 100
}
Now i want this method to be able to accept Car2 also and change the way it calculates its speed. Do i need to rewrite the class and method or is there an easier way to do it?
Keep in mind that i dont want to completely modify Car, i just want to have both Car and Car2 and use them on demand in the same classes without having to rewrite all of them.
Thanks!
You can override the methods of super class (Car) inside a sub class (Car2), which is called polymorphism, which is one of the core principles of OOP. This principle allows us to invoke different class behaviours depending upon the actual object (Car or Car2 object) passed at runtime.
For your problem, you can follow state pattern which will provide dynamic behavior depending upon the type passed and the actual implementation of checkSpeed(), as shown below:
SpeedChecker class:
public class SpeedChecker {
int checkSpeed(Vehicle v) {
//depending upon the Vehicle type object passed, checkSpeed() will be called
v.checkSpeed();
}
}
Car Class:
public Car implements Vehicle {
int checkSpeed(Car c) {
//Add specific logic for Car
}
}
Car2 Class:
public Car2 implements Vehicle {
int checkSpeed(Car c) {
//Add specific logic for Car2
}
}
as Sami Kuhmonen says :
If Car2 inherits from Car it is a Car itself
I will detail. You said :
Now i want this method to be able to accept Car2 also and change the
way it calculates its speed. Do i need to rewrite the class and method
or is there an easier way to do it?
If you don't add methods but modify their content, you should reason by programming by interface or in more general way by programming by suitable common ancestor component.
In Java, polymorphism allows not to type specifically an instance when you declare it if a base class or an interface is more suitable.
Here :
int checkSpeed(Car c) {
speed = c.attributeX * 100
}
you can send as parameter a Car or any subclasses of it, there a Car2.
So you should keep Car base class as declared type when it is suitable, especially in methods which may take the one or the other type.
It will work :
Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car c) {
speed = c.attributeX * 100
}
It will not compile :
Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car2 c) {
speed = c.attributeX * 100
}
You can check if the object Car c is actually of type Car2:
int checkSpeed(Car c) {
if(c instanceof Car2){
//do something if c is actually Car2, such as
use attributes that exist in Car2 but not in Car
else{
//the regular case
speed = c.attributeX * 100
}
}
Keep in mind that i dont want to completely modify Car, i just want to have both Car and Car2 and use them on demand in the same classes without having to rewrite all of them.
You already have a broken design since your sample method violates the most important principle in OOP: information hiding. Refusing to fix that because it's a lot of work will cause much more work later, just as it is doing now. This extra work will grow exponentially and harm you deadlines...
For example a method that does not belong to Car class.
int checkSpeed(Car c) {
speed = c.attributeX * 100
}
Lets forget for a moment that this doesn't even compile...
Now i want this method to be able to accept Car2 also and change the way it calculates its speed. Do i need to rewrite the class and method or is there an easier way to do it?
If this method would be part of the Vehicle interface and implemented in Car (and Bicycle) you could simply implement it in Car2 any way you want. without changing anything else in your program.
And That's what OOP is all about. But you get that advantage only if you know and follow its principles...
Сlearer approach in this case would be letting the Vehicle object itself to determine how should speed be calculated. This makes sense since all information is needed to do that is already encapsulated in the Vehicle class.
What I mean is have an interface like that:
pulbic interface Vehicle {
int getSpeed();
}
And implementations of the interface. For Car:
public class Car implements Vehicle {
// some car stuff
...
#Override
public int getSpeed() {
return carspeed;
}
...
}
And for Car2:
public class Car2 implements Vehicle {
// some car2 stuff
...
#Override
public int getSpeed() {
return car2speed;
}
...
}
Now your checker method can look like this:
public int checkSpeed(Vehicle v) {
int speed = v.getSpeed();
// do the checks
...
return someResult;
}
This way you don't really need to know the type of the vehicle itself to be able to check its speed. This is the whole point of polymorphism.
And in case you can't modify existing interface, I would suggest you to extend original Vehicle interface with SpeedVehicle that contains all required methods, and build a class hierarchy based on it.
If Car2 is always a Car and needs all the behaviors of Car, then you need to make Car2 a inherit from Car. If Car2 is not always a Car, but they have common ground, then you need to determine what that common ground is, implement it as a BaseCar class or an ICar interface if the implementations totally differ and Car along with Car2 should be inherited from BaseCar/ICar.
Related
I'm writing a program our professor has given us as homework.
I have a class called Car, that has two private real members x and y, which are supposed to represent the coordinates of the car in the coordinate plane, and I wanted to implement an interface called MyInterface, in which I declared a method public boolean compare(Object t). It was stated it has to be Object t and not something else, so that I can implement the interface in multiple classes (part of the homework). Java is the programming language in question.
The part of the code that that is problematic looks like this:
public interface MyInterface {
public boolean compare(Object t);
}
public class Car implements MyInterface{
private double x, y;
#Override
public boolean compare(Car t) {
double curdist = Math.sqrt(this.x*this.x + this.y*this.y);
double givdist = Math.sqrt(t.x*t.x + t.y*t.y);
if(curdist < givdist) return true;
else return false;
}
}
My method compare needs to calculate the distances from the point (0,0) for the current car and the given car, and compare the two distances. If the current car's distance (curdist) is closer from the given car's distance (givdist) to (0,0), compare returns true, otherwise it returns false.
My question is, how do I correctly implement this method in the class Car?
I've tried a few things, but none of them seem to work out. Any help is appreciated, 'cause I am quite new to object-oriented programming. Thanks in advance.
If you must have Object as the parameter type for compare, then you must test the class of the parameter passed in to make sure it's a Car first.
Change the compare argument to Object in your Car class. Then the #Override annotation will determine that the method is properly overriding the instance method, and you won't get a compiler error. Use the instanceof operator to determine if t is a Car. You may decide to throw an IllegalArgumentException if it isn't a Car, or if it's null. Then you can cast it to a Car and continue with the logic of your method.
Even if you have to do have it take Object for your class, a better way to do this in general is with generics. Here, this would answer the question "What is this class comparable to?". If you've covered generics, then you may understand a class that is defined as MyInterface<T>. The compare method would take a parameter of type T. This allows you to implement the method in Car with a parameter of type Car, provided Car implements MyInterface<Car>. This is similar to the existing Comparable interface built-in to Java.
In the question,I learned that the polymorphism has 4 types:
Coercion,
Overloading
Parametric Polymorphism
Inclusion
So I did not completely understand what does mean by Inclusion, I need same example to implement this notion.
As already suggested, search a little bit yourself to get a deeper idea of this topic... Here is one possible explanation:
[...] subtyping allows a function to be written to take an object of a certain type T, but also work correctly, if passed an object that belongs to a type S that is a subtype of T (according to the Liskov substitution principle) Wikipedia - Polymorphism
abstract class Vehicle
{
abstract void move();
}
class Car extends Vehicle
{
public void move() { ... }
}
class Ship extends Vehicle
{
public void move() { ... }
}
public void moveVehicle(Vehicle v)
{
v.move();
}
Here is an example for inclusion polymorphism:
Vehicle [] vs = new Vehicle [2];
vs[0] = new Car();
vs[1] = new Ship();
for(Vehicle v : vs)
{
moveVehicle(v);
}
Or another example:
Car c = new Car();
Ship s = new Ship();
moveVehicle(c);
moveVehicle(s);
For additional information see the Wikipedia - Polymorphism page... But still search yourself for this topic to get a deeper idea of it!
The inclusion polymorphism means that you can instantiate an object from his super class.
For example you have
public class Person {
.
.
}
public class Employee extends Person{
.
.
}
So you can create an object
Person x = new Employee();
This is useful for example if you need to create a lot of different object that refere to a single superType
For example you have SuperTyper geometric_figure and SubTyper figure (circle, square, triangule,..). The geometric_figure may have two attributes x,y for the screen location and an abstract method "draw",to draw on screen, that each figure ,that extend it , need to implement
Thanks to dynamic link of java when you call geometricFigure.draw(), it will automatically know what type of geometric_figure you are calling (circle, square, triangule,..), and invoce this draw method
To manually check what is his specific class you can do:
Geometric Figure x = new Square();
if(x instance of Square){...}
A popular case is when you want to refere to a generic object like this
Object x = new AnyClass();
because the Object is the generic super class that every class have. (When you do not extend anythig, by default it extand Object)
So I am trying to make a simple RPG-like text-based game to consolidate some of my studies, and I am wondering how the best way to implement this type of setup is:
Interface called Fighter > implemented by AbstractFighter > MagicFighter and StrengthFighter extend AbstractFighter. (Originally MagicFighter and StrengthFighter had their own interfaces with additional unique behaviours) but...
Now where it gets confusing is I want the player to be able to choose between these two types of Fighter, I then store this in a List(Fighter). So obviously the type I get back is always Fighter (it has to be as I dont know which implementation of Fighter the user will choose) and I can only call methods that are in the Fighter interface
One thing I could do is to write checks for what the player chose and downcast every time I need to call methods unique to the different Fighter implementations. But this would mean alot of repeated code, and sounds messy =/.
Another possibility is to run checks and add the user to a List(StengthFighter) or List(MagicFighter) based on their choice, but ultimately this just has the exact same problem as the previous 'solution'.
The final thing I can think of is to try and mirror each implementation of Fighter so that there is always a version of each behaviour for each. So for example
void regen(); in the Fighter interface and then implemented differently for StrengthFighter and MagicFighter (Magic fighter might regen mana, strength fighter might regen rage whenever he uses an attack() (which is another issue as due to ManaFighter needing to implement regen() it is obviously public, but the use of it within StrengthFighter would be private).
Anyway, you probably get the gist by now, so il save any more textwalling.
What it boils down to; is this a flaw in my implementation. Or is this just an inevitability with OO programming? I mean, at the end of the day, how can Java know what type the result needs to be (and therefore use its methods) if it is asking the user to make a decision that determines the type.
This is a rough class implementation based on interpretations of your question. Your original definition of having an interface and then an implementation and then the individual types feels complex. Instead, we want to work with individual Fighters and not representations of them.
class Fighter {
int hp;
void attack() {
}
void move() {
}
void regen() {
hp++;
}
}
class MagicFighter extends Fighter {
int mana;
#Override
void regen() {
mana++;
//we don't regen hp because we're magic-type.
}
}
class StrengthFighter extends Fighter {
int rage;
#Override
void attack() {
super.attack();
specialRegen();
}
void specialRegen() {
rage++;
}
#Override
void regen() {
// does nothing
}
void berserk() {
rage--;
}
}
In this case, we could store a list of Fighter
List<Fighter> fighters = new List<>();
When we want to create a new fighter, we would determine what the user wanted and add that to the list of fighters.
if (selection.equals("StrengthFighter")) {
Fighter fighter = new StrengthFighter();
fighters.add(fighter);
}
Then, we'd call all the methods as normal. Anything shared between the two classes would not be overridden, such as Fighter.move. Anything that doesn't work for only one type would be overridden, like StrengthFighter.regen. Anything that has special additional functionality for a specific type would implement the additional functionality and make a super call, like StrengthFighter.attack.
Basically, you have the right idea already, but basically, you want Fighter to do as much of the shared work as possible, and then implement individual actions based on the type behind the scenes. If something needs to be checked for type, it needs to be something unique to that type of Fighter, such as StrengthFighter.berserk.
This reduces the need to check types except when they really matter.
I think you have the only Fighter > FighterImpl. Other staff should be implemented separately: weapons, armor, abilities, etc...
On creation you grant the fighter with abilities + weapon (restricted by abilities) + perks. Then all fighters live in the same conditions.
interface Fighter {
int getSpeed(); // base fighter speed per time unit
Armor getArmor();
Weapon getWeapon();
Damage attack(Fighter enemy); // animate + apply damage
Position move();
List<Perks> getPerks();
List<Ability> getAbilities();
}
interface Weapon {
DamageType getDamageType();
int getDamage();
void animateHit(Fighter enemy);
}
abstract class AbstractWeapon implements Weapon {
...
}
abstract class MeleeWeapon extends AbstractWeapon {
...
}
abstract class MagicWeapon extends AbstractWeapon {
...
}
A simple question on Java class
I want to create my class with my own add method which adds an object of a different class.
For eg if my class name is Weapon, I want to create an add method like void add(Gun gun) (Gun being one of my other classes for example)
This would be just like creating your own collection maybe??? if I am not wrong? Like list.add() method, I want to implement my own add method for the Weapon class
So when I instantiate an object of my weapon class, it should be like
Weapon w = new Weapon(new Gun( ... .. constructor parameters) )
Also I would like to have variants of my add methods. Like a different add method with different parameters like void add(Weapon weapon) ( creating an method to add your own class object )
So I am not sure if this is similar to implementing a collection?? And if it is how do I achieve it? Do I have to extend another class for this?
Apologies if my question confused anyone! :)
List<Object> weapons = new ArrayList<Object>();
weapons.add(new Sword());
weapons.add(new Gun());
try this.
You don't necessarily have to do a new Gun() when you instantiate. You can just do the following:
class Weapon
{
private Gun gun;
public Weapon()
{
gun = new Gun(); //etc.
}
//add more methods here. You can use gun.function() to invoke any functions
}
As for using a Weapon object, just declare public methods in the Weapon class and then invoke them in your methods.
For example, the add() function:
class Weapon
{
...
public int val() { return 0; } // don't know, some random method.
}
Then on a different file:
int add(Weapon w)
{
return Weapon.val() + 1111; //perform something here
}
I hope this answers your questions, it was a little bit unclear :|. Comment if you need more help.
Your question is a bit unclear to me, but I'll try my best.
If you want to have a List of Weapon, then you need to use inheritance. In your example, A Gun is-a Weapon. Therefore, you can do class Gun extends Weapon. Then, let's say you're using an ArrayList, you would instantiate it like:
List<Weapon> weapons = new ArrayList<Weapon>();
You can now call add with a Gun, or any other sub-class of Weapon like so:
weapons.add(new Gun()); //or
weapons.add(new Cannon());
If you actually need to add a Gun to a Weapon (Which doesn't really make sense...), you can use composition. See Shahar's answer for a more detailed explanation of this behavior.
Just to clarify, no matter what, I'm pretty sure creating a new Collection is not what you want to do here.
These are a lot of questions :-) let's enumerate them
creating a method called add() into an object makes this object a Collection? No. To be a Collection, a class must implement the interface java.util.Collection or implement any one of the subinterfaces or extend any of the subclasses that implement this interface. A list of them is available in the Collection javadoc - http://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
if I want to add an object into another, it must be via the constructor? e.g. new Weapon(new Gun())? Not necessarily. You can just create a Weapon w = new Weapon() and then add the Gun reference via a method such as w.setGun(new Gun()). Anyway, any constructor with one or more parameters must be declared explicitly in your class. Only the non-parameter constructor is available by default.
Now, let's suppose that you want to store a class Gun that is a subclass of a class Weapon. Then you first need to define the hierarchy between them, for example
class Weapon{
}
class WeaponWithBlade extends Weapon{
}
class Sword extends WeaponWithBlade{
}
class Knife extends WeaponWithBlade{
}
class Gun extends Weapon{
}
and then you want to store all these weapons in a Weapon collection.
since all of them are subclasses of the Weapon class, it's valid to do something like this
java.util.List<Weapon> weapons = new java.util.ArrayList<>();
weapons.add(new Sword());
weapons.add(new Gun());
notice that both List and ArrayList are collections (List is an interface and ArrayList is a concrete class that implements the List interface), parametrized to be collections of Weapons.
I hope this can help you.
Let's say I have an object of the class Car, with like 30 variables ranging from top speed to color. I want to make a MyCar object (class MyCar extends Car) that is basically the same thing except it stores some more information.
It is not possible for me to create MyCar objects right away (since out of thousands of Car objects only a few will become MyCar objects), unless I leave the additional fields blank, but that doesn't seem too professional. And neither does creating a constructor which takes 30 arguments, or setting 30 arguments through method calls.
So, is there any way to easily inherit all the variables from a superclass object?
PS: My program is not about cars, but I figured it would be an easier example.
EDIT
Thanks for the replies. They are all helpful for my program, but not for this particular problem. Builders don't seem beneficial because these cars of mine don't have default values for their variables. Every time a car is made, all the variables are filled out (which is needed to construct a sort of "fact-sheet").
Envelopes are an interesting design, but still require me to copy all the variables in the subclass constructor. I was hoping there would be a way to circumvent this. Templates would also require me to copy all the variables one by one.
In my program the subclass acts as a sort of "wrapper class" in a search engine. The subclasses are the same as the normal cars, but they have a "ranking score". My program is designed to display regular cars, and by extending those I can easily display the subclasses and order them by score at the same time.
I have to create new objects anyway, because multiple searches can be performed on the same list of cars. So editing variables in the original cars was not an option.
Maybe there is a better solution to this problem, but for now I guess I'll have to pass the superclass object into the constructor and copy all the variables there.
Thanks for the help!
PS: I'm just thinking, perhaps I could throw all the variables into a HashMap. That way I could access them by using .get(varname), and I would only have to pass one HashMap variable into the subclass. Downside is I would have to cast a lot, since the vars are a mixture of Strings, ints, doubles etc. What do you think, is it acceptable coding style?
Effective Java 2nd Edition, Item 2: Consider a builder when faced with many constructor parameters
And neither does creating a
constructor which takes 30 arguments,
or setting 30 arguments through method
calls.
If you are facing a constructor with too many parameters then you might want to have a look at: The Builder Pattern.
The idea is to set only the field you want/know into the builder, without bothering with the optional ones, or ones that you'd want to use default values, then calling build() to construct the actual object. See the Java examples in that article.
Once you have setup that pattern, you can construct Cars this way (notice the clean structure):
Car car = new Car.Builder(required_param1, required_param2)
.color(RED) // optional params
.topSpeed(300)
.zeroToHundred(2)
.build();
You can add a constructor that gets a Car object and copy the values from the Car to the new MyCar.
It is not possible for me to create MyCar objects right away (since out of thousands of Car objects only a few will become MyCar objects),
So, you'll have lots of objects of Car type, a few of which you'd like to, at runtime, "promote" to SpecialCar type?
Do SpecialCars have exactly the same interface as Cars?
You might want to read up on Coplien's Envelope-Letter Pattern, it's a way of "changing" object type at runtime. The object doesn't really change type, of course; instead, a different "Letter" goes into the existing "Envelope". The Envelope is the handle that other code references, but method calls on the Envelope are delegated to the Letter:
class CarEnvelope { // an envelope
Car c ; // the letter
CarEnvelope( Car c ) { this.c = c ; }
int someMethod() {
return c.someMethod(); // delegate
}
void promoteToSpecialType() {
if( ! c.isSpecialCar() ) {
c = new SpecialCar( c ) ;
}
}
class Car {
Car() {}
int someMethod() { do Car stuff }
boolean isSpecial() { return false; }
}
class SpecialCar extends Car {
SpecialCar( Car c ) { /*copy c's attributes...*/ }
int someMethod() { do SpecialCar stuff}
boolean isSpecial() { return true; }
}
CarEnvelope c = new CarEnvelope( new Car() ) ;
// do stuff with c
c.someMethod(); // indirectly calls Car.someMethod();
// promote
c.promoteToSpecialType();
c.someMethod(); // indirectly calls SpecialCar.someMethod
OP here.
I understand that this looks like laziness. But I already have it working by manually copying 30 variables in the constructor. Not that big of a task, I know.
The thing is, I have been taught to code with style. When I see mindless code blocks that look like copypasta my instincts tell me that there is probably a better way. So my desire to learn and strive for perfection has driven me here.
But if there really is no other way than to copy the variables (or override all the get&set methods) then I don't have to look any further.
Needless to say, all the replies in this topic have given me new insights. Thanks guys.
I have a feeling that what you are looking for is the notion of a template; e.g.
public class Car {
private final int attr1;
private final int attr2;
...
public Car() {
super();
}
/* copy constructor */
public Car(Car template) {
this.attr1 = template.attr1;
this.attr2 = template.attr2;
...
}
/* setters and getters */
}
Then ...
Car myTemplate = new Car();
myTemplate.setAttr1(3);
myTemplate.setAttr2(11);
...
Car car1 = new Car(myTemplate);
car1.setAttr1(4);
Car car2 = new Car(myTemplate);
car1.setAttr1(5);
I don't get it. What's wrong with a regular inheritance?
class Car {
private int attributeOne;
.....
private boolean attrbuteThirty;
public void methodOne(){...}
...
public void methodThirty(){...}
}
And then just subclass it:
class SubCar extends Car {
private int extraAttribute;
}
All the 30+ attributes and methods are already inherited, that's what the extends is all about.
If what you need is to create a new object based on the data of an existing one, but you're resisting to code it! ( ¬¬ ) , then you may just create a small script to create the code for you. It's very easy. You copy/paste the generated code and you're done.
If you don't want to do it, because you don't want to duplicate the data, you may override interesting methods, and delegate the code to the original, that's what the Decorator design pattern is all about:
class SubCar extends Car {
private Car wrapped;
private String extraAttribute;
public SubCar( Car original, String newAttributeOne ) {
wrapped = original;
this.extraAttribute = newAttributeOne;
}
public void someMethod() {
wrapped.someMethod();
}
public String getName() { return wrapped.getName(); }
... and so on
// new method
public String extraAttribute() { return extraAttribute; }
}
That way you won't duplicate the data, but just decorate it.
We can create an interface ICar that has all the getters and setters for all the 30 columns.
Car can implement ICar and can contain all the 30 fields with their corresponding getters and setters.
MyCar can also implement ICar and can use composition. It exposes Car's methods as delegate methods (which can automatically be generated in an IDE like eclipse)
public interface ICar {
// getter and setter methods
}
public Car implements ICar {
private String color;
// getters and setters for each of the fields
}
public MyCar implements ICar {
private Car car;
public MyCar(Car car){
this.car = car;
}
public String getColor() {
return car.getColor();
}
}
All consumers could then use the ICar interface for their manipulation. Will that work?