My main question is if I can bind a generic object two 2 types if the it is extended by e.g. 4 types. I do not really know how to ask this question without an example.
So i created a little example of a simple game in which Warriors or Rangers can equip different type of Weapons(OneHanded, TwoHanded, Melee, Ranged). Every Weapon has two attributes. So the e.g. the Weapon type Dagger extends Weapon implements OneHanded, Melee.
Ranger class (can use two-handed, ranged Weapons):
private Weapon weapon;
public <T extends TwoHanded & Ranged> void equip(T weapon) {
this.weapon = (Weapon) weapon;
}
Warrior class (can use one-handed, two-handed, melee, ranged weapons):
private Weapon weapon;
public <T extends OneHanded & Melee & Ranged> void equip(T weapon) { //probably have to do this differently
this.weapon = (Weapon) weapon;
}
Bow and Dagger class:
public class Bow extends Weapon implements TwoHanded, Ranged {}
public class Dagger extends Weapon implements OneHanded, Melee {}
public void equipTest() {
ranger.equip(bow); //works fine
warrior.equip(dagger); //does not work
}
The main problem here is (I think) that I do not know how to implement it that a warrior can equip different weapons with different attributes(e.g. bow(ranged, two-handed) or also dagger(melee, one-handed)) whereas the ranger has only one possibility. How can I workaround this problem?
The code does not compile because Dagger does not implement Ranged.
I think you mean Melee or Ranged. This could be written as overloads.
<T extends Melee & OneHanded> void equip(T weapon) {
<T extends Ranged & OneHanded> void equip(T weapon) {
Note change of order in order for the overload to have distinct erasures. However, it is much better to have distinct names rather than overload.
(Also, I'd use a layer of indirection instead of losing the type information with a base type.)
The other answer directly addresses the issue in the question. As you can see, using this design, the best option for you is to end up with a bunch of equipXXX() methods.
An alternative would be to use the decorator pattern.
Create abstract Weapon and WeaponDecorator to allow maximum flexibility for later adding new weapon types.
public abstract class Weapon {
...
}
public abstract class WeaponDecorator extends Weapon {
Weapon _weapon;
WeaponDecorator(Weapon weapon) {this._weapon = weapon;}
}
Convert various weapon types to act as weapon decorators:
public class OneHanded extends WeaponDecorator {
OneHanded(Weapon weapon) {
super(weapon);
}
}
public class Melee extends WeaponDecorator {
Melee(Weapon weapon) {
super(weapon);
}
}
and remove all generics from the Warrior class too:
public class Warrior {
private Weapon weapon;
public void equip(Weapon weapon) {
this.weapon = weapon;
}
}
Now you can simply do:
Weapon w = new OneHanded(new Melee(new Dagger()));
Warrior warrior = new Warrior();
warrior.equip(w);
Here is a full example with code and more explanation.
EDIT:
If you choose this solution, the responsibility of checking the validity of selected weapon for a selected hero should also be addressed in run time. For example, this can be added to Ranger's equip method:
if(weapon.isMelee()) //error (unacceptable)
But as the set of rules grow complex, you might want to use other patterns such as the command pattern. Still, all of this will be delegated to run time. This is the price that you pay for acquiring more flexibility. Of course, you can also try to acquire some compile-time safety by creating a hierarchy of decorators (similar to what java.io library does). However, this could make the application overly complicated very fast.
In the end, if there are only a few of this combined types (TwoHanded + Melee, OneHanded + Ranged, etc) it makes sense to go with the other answer and just have a few more equip methods and have the safety of compile time type checking.
Related
I have two abstract classes: Char and Weapon. Each has two derivative classes: King and Troll, and Club and Sword.
A character always has a weapon, but the type is not specified. So when building the Char class I cannot initialise the correct type. Also, when choosing a character, I similarly cannot initialise the correct type.
Is it wrong to initialise an abstract class? How can one initialise a class of one sort and then change the variable class? Provided the new type is a trivially different inheritation of the same parent class? Or should one go about it completely differently?
It may very well be that I haven't even understood the concept of an abstract class. I'm new to Java and pure OOP.
public class Player{
private Char c; // Wrong?
public void changeChar(int charID, int wepID){
switch(charID){
case 1: c = new King(wepID); break;
case 2: c = new Troll(wepID); break;
}
}
public void fight(){
c.fight();
}
}
abstract class Char{
protected String name;
public Weapon weapon; // Wrong?
Char(int wepID){
switch(wepID){
case 1: weapon = new Sword(); break;
case 2: weapon = new Club(); break;
}
}
public void fight(){
weapon.useWeapon(name);
}
}
abstract class Weapon{
protected String wepName;
public void useWeapon(String user){
System.out.println(user + " fights with " + wepName);
}
}
class Club extends Weapon{
Club(){
wepName = "Club";
}
}
class Sword extends Weapon{
Sword(){
wepName = "Sword";
}
}
class Troll extends Char{
Troll(int wepID){
super(wepID);
name = "Troll";
}
}
class King extends Char{
King(int wepID){
super(wepID);
name = "King";
}
}
You cannot instantiate an abstract class. A smarter way to go is to provide your constructor for Char a Weapon instance as a parameter - you could simply use it in Char.
abstract class Char{
protected String name;
public Weapon weapon;
Char(Weapon weapon){
this.weapon = weapon;
}
public void fight(){
weapon.useWeapon(name);
}
}
class Troll extends Char{
Troll(Weapon weapon){
super(weapon);
name = "Troll";
}
}
and later in your code:
Char troll = new Troll (new Club());
In Java, abstract classes are allowed to have one or more methods that are specified, but not implemented. They are meant to be used as "the highest common denominator" for subclasses that share majority of functionality, except a few methods. Therefore, Java prohibits you from creating an instance of an abstract class, and requires any subclass to provide implementations of abstract methods. This is by design. The basic idea behind it is to promote code reusability, but in real life, it's a mix of trade-offs so your mileage might vary. Most of the time, you can achieve a similar effect with a combination of non-abstract base classes and interfaces.
Based on your example, Char does not have to be an abstract class, but Weapon is a good candidate because it has a "useWeapon" method. You can declare "useWeapon" as abstract in Weapon, and provide different implementations in Sword and Club. Alternatively, you could make a Weapon an interface. The abstraction you want to make here is that a Char can use a Weapon without knowing whethere the actual weapon is a Club or Sword. This means you can give a Char anytime a weapon of any kind, and everything should work. Instead of passing a Char an "int" in constructor, it's actually better to pass it the Weapon itself.
I was reading Eric Lippert blog about Wizards and Warriors. Interesting read, but I found certain parts hard to understand (not the authors fault, I'm only a beginner in OOP).
He presents the problem of two character types within a game, a Wizard and a Warrior, and the rules are:
A warrior can only use a sword.
A wizard can only use a staff
In the blog, he uses a getter/setter in the first part to handle the weapon for the character, but let's change it to an inventory system. So, we have an abstract class called Player with a list of items(ArrayList).
interface Weapon {
attack(Enemy enemy);
}
public class Staff implements Weapon {}
public abstract class Player {
private List<Weapon> weaponInventory;
//left out constructor and other methods to keep it on point
abstract void add(Weapon add)
}
and use it like so:
public class Wizard extends Player {
#Override
public void add(Weapon add){
//code to add weapon;
}
}
How would you structure the add method to enforce the rule that a Wizard can only use a staff? I thought of calling getClass() or getType() on weapon but those are considered bad practice.
The best answer I could come up with was have a String variable called type, and a getter in the Weapon interface. During object construction, set the type to sword or staff. However, this doesn't really help, as you could create a sword object, pass in staff as the type, and use it.
How would you prevent a sword from being added to the wizards inventory?
How would you structure the add method to enforce the rule that a Wizard can only use a staff?
Either you didn't read the whole series, or you didn't understand its central message. The entire point of that series of articles is to express that there is no good way to structure a method that enforces a restriction on the relationship between subclasses.
This is simply a fact about subclass-based OOP; there are some things it does not model well, and this is one of them. A fundamental principle of many OOP type systems, including that of Java and C#, is Liskov's: that you can always use an instance of a subclass where an instance of a superclass is needed. That makes modeling restrictions in the type system difficult.
In the last part of the series I give the best solution that I know of: model the rules of the simulation as objects themselves, and have a rule enforcer class that gives the user feedback when they attempt to violate a rule. Don't make the type system try to solve your business problems.
You could use something like the following. Note: in the Player class, the weapons can be of any type. However each sub-class of player has its own specific add(). So while this approach enforces the required rules, it loses a little generality.
public class Staff implements Weapon {}
public class Sword implements Weapon {}
public abstract class Player {
private List<Weapon> weaponInventory;
protected final void addWeapon(Weapon weapon) {
weaponInventory.add(weapon)
}
}
public class Wizard extends Player {
public void add(Staff staff) {
addWeapon(staff);
}
}
public class Warrior extends Player {
public void add(Sword sword) {
addWeapon(sword);
}
}
You could use generics:
Weapon and Staff classes remain the same:
public interface Weapon {
void attack(Enemy enemy);
}
public class Staff implements Weapon {
#Override
public void attack(Enemy enemy) {
//Do ur attacking. :)
}
}
The Player class has a generic type:
import java.util.ArrayList;
import java.util.List;
public abstract class Player<T extends Weapon> {
protected List<T> weaponInventory = new ArrayList<>();//Made protected so Wizard can access it.
public abstract void add(T weapon);
}
And the Wizard class extends Player<Staff> (NOT just Player):
public class Wizard extends Player<Staff> {
#Override
public void add(Staff weapon) {
// Add the staff to the list declared in Player
weaponInventory.add(weapon);
}
}
Explanation:
The T in Player<T> is the type of weapon that you want the player to use.
When you extend Player<Staff> in the Wizard class, you're saying that you want Wizard to be a Player that only uses Staffs. This way, the Wizard's weaponInventory list will contain only Staffs.
When you add the Warrior class, it would extend Player<Sword>, which would make its weaponInventory only take Swords.
By the way, I instantiated weaponInventory in the above code and implemented the add method in Wizard.
Java - Is it possible to extend all the subclasses of a class with a single class?
Let's explain it with an example, the actual code is quite more complex. I have an Animal class with its own class hierarchy. Let's say that it has two subclasses: Testarrosa and Viper.
public class Car {
public abstract String getManufacturer();
}
public class Testarossa extends Car{
public String getManufacturer(){
return "Ferrari";
}
}
public class Viper extends Car{
public String getManufacturer(){
return "Dodge";
}
}
I want to extend all the Car subclasses with a RegisteredCar subclass.
public class RegisteredCar extends Car {
private String plateNumber;
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
At some point, I should be able to create a new RegisteredCar of a specific subclass. Something like
RegisteredCar c = new RegisteredCar<Viper>("B-3956-AC");
And call the c.getManufacturer() to obtain "Dodge" and c.getPlateNumber() to obtain B-3956-AC. Obviously, I should still be able to create a Car c = new Viper();
That is an example. Having an attribute in Car with null value if not registered is not enough for what I need.
In short, no that is not possible. You have to unfortunately modify your object model.
For example, what about having a Registration class this way:
public interface Registration<C extends Car> {
C getCar();
String getPlateNumber();
}
This way you can extract the information relating to registration in a single class, while maintaining your Car models.
You can then do helper methods like:
Registration<Viper> registeredViper = createRegistration(new Viper(), "B-3956-AC");
As others have said, no thats not really possible and your example could be solved by changing your model
As an alternative to inheritance you could use another class to wrap a Car instance.
I would make Car an interface (though having RegisteredCar extend Car should work too) and then attempt something like the following pseudo code:
class RegisteredCar<T extends Car> implements Car {
private final T car
RegisteredCar(T car) {
this.car = car;
}
... methods for RegisteredCar
... methods from Car delegating to `this.car`
}
Please excuse the somewhat bad code, I don't have an IDE open, and I always mess up generics without an IDE to hand.
Another possible solution is to use AOP, though I don't know how in fashion that is these days as but what you are describing could be a cross cutting concern.
A final alternative might be to use a language that allows for Extensions, Traits, Protocol or some other type of 'mix in'
In java it is prohibited to extends more than 1 class.
You could build chain from classes to extends, for example.
To solve the problem of mutiple inheritance in Java → interface is used
You should avoid inheritance as much as possible. Use abstractions (interfaces) to make your code elegant and maintainable. Just google why extends is evil.
public interface Car{
String getManufacturer();
}
public interface Registerable{
boolean isRegistered();
void register(String plateNumber);
void getPlateNumber();
}
public class Viper implements Car, Registerable
{
//all methods
}
With Generic class approach as described in other answer, you will not be able to use RegisteredCar where your require to pass Car object. e.g. suppose you need to generate some invoice.
Invoice getInvoice(Car c);
In this method you cannot use RegisteredCar as it is not of Type Car. All you API which require Car are not applicable to RegisteredCar. In some cases you may need Plate Number as well as Car, There you may need to keep mapping of Plate Number and Cars. I would suggest following approach based on Decorate Pattern and delegate all Car calls to passed car object
public class RegisteredCar extends Car{
public RegisteredCar(Car c, String plateNumber){
}
#Override
String getColor(){
c.getColor();
}
}
No, it's not like C++. Multiple inheritance is not possible in Java. However you can implement multiple interfaces.
You cannot achieve that with inheritance.
Your best option is making the RegisteredCar type generic, then having a generic instance variable that holds the intended type car:
public class RegisteredCar<T extends Car> {
private String plateNumber;
private T car;
public T getCar() {
return this.car;
}
public T setCar(T car) {
this.car = car;
}
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
With this, you will be able to pass into RegisteredCar an object of any type that's a subclass of Car.
As you can notice, I have removed the extends Car part of this class, as it doesn't need to be a subclass of car itself.
Is there a reason, in the real classes, that you couldn't simply add the new feature to the existing base class?
public abstract class Car
{
public abstract String getManufacturer() ;
protected String plate_number = null ;
public String getPlateNumber()
{ return this.plate_number ; }
public boolean isRegistered()
{ return ( this.plate_number != null ) ; }
}
In an attempt to fully understand how to solve Java's multiple inheritance problems I have a classic question that I need clarified.
Lets say I have class Animal this has sub classes Bird and Horse and I need to make a class Pegasus that extends from Bird and Horse since Pegasus is both a bird and a horse.
I think this is the classic diamond problem. From what I can understand the classic way to solve this is to make the Animal, Bird and Horse classes interfaces and implement Pegasus from them.
I was wondering if there was another way to solve the problem in which I can still create objects for birds and horses. If there was a way to be able to create animals also that would be great but not necessary.
You could create interfaces for animal classes (class in the biological meaning), such as public interface Equidae for horses and public interface Avialae for birds (I'm no biologist, so the terms may be wrong).
Then you can still create a
public class Bird implements Avialae {
}
and
public class Horse implements Equidae {}
and also
public class Pegasus implements Avialae, Equidae {}
Adding from the comments:
In order to reduce duplicate code, you could create an abstract class that contains most of the common code of the animals you want to implement.
public abstract class AbstractHorse implements Equidae {}
public class Horse extends AbstractHorse {}
public class Pegasus extends AbstractHorse implements Avialae {}
Update
I'd like to add one more detail. As Brian remarks, this is something the OP already knew.
However, I want to emphasize, that I suggest to bypass the "multi-inheritance" problem with interfaces and that I don't recommend to use interfaces that represent already a concrete type (such as Bird) but more a behavior (others refer to duck-typing, which is good, too, but I mean just: the biological class of birds, Avialae). I also don't recommend to use interface names starting with a capital 'I', such as IBird, which just tells nothing about why you need an interface. That's the difference to the question: construct the inheritance hierarchy using interfaces, use abstract classes when useful, implement concrete classes where needed and use delegation if appropriate.
There are two fundamental approaches to combining objects together:
The first is Inheritance. As you have already identified the limitations of inheritance mean that you cannot do what you need here.
The second is Composition. Since inheritance has failed you need to use composition.
The way this works is that you have an Animal object. Within that object you then add further objects that give the properties and behaviors that you require.
For example:
Bird extends Animal implements IFlier
Horse extends Animal implements IHerbivore, IQuadruped
Pegasus extends Animal implements IHerbivore, IQuadruped, IFlier
Now IFlier just looks like this:
interface IFlier {
Flier getFlier();
}
So Bird looks like this:
class Bird extends Animal implements IFlier {
Flier flier = new Flier();
public Flier getFlier() { return flier; }
}
Now you have all the advantages of Inheritance. You can re-use code. You can have a collection of IFliers, and can use all the other advantages of polymorphism, etc.
However you also have all the flexibility from Composition. You can apply as many different interfaces and composite backing class as you like to each type of Animal - with as much control as you need over how each bit is set up.
Strategy Pattern alternative approach to composition
An alternative approach depending on what and how you are doing is to have the Animal base class contain an internal collection to keep the list of different behaviors. In that case you end up using something closer to the Strategy Pattern. That does give advantages in terms of simplifying the code (for example Horse doesn't need to know anything about Quadruped or Herbivore) but if you don't also do the interface approach you lose a lot of the advantages of polymorphism, etc.
I have a stupid idea:
public class Pegasus {
private Horse horseFeatures;
private Bird birdFeatures;
public Pegasus(Horse horse, Bird bird) {
this.horseFeatures = horse;
this.birdFeatures = bird;
}
public void jump() {
horseFeatures.jump();
}
public void fly() {
birdFeatures.fly();
}
}
May I suggest the concept of Duck-typing?
Most likely you would tend to make the Pegasus extend a Bird and a Horse interface but duck typing actually suggests that you should rather inherit behaviour. As already stated in the comments, a pegasus is not a bird but it can fly. So your Pegasus should rather inherit a Flyable-interface and lets say a Gallopable-interface.
This kind of concept is utilized in the Strategy Pattern. The given example actually shows you how a duck inherits the FlyBehaviour and QuackBehaviour and still there can be ducks, e.g. the RubberDuck, which can't fly. They could have also made the Duck extend a Bird-class but then they would have given up some flexibility, because every Duck would be able to fly, even the poor RubberDuck.
Technically speaking, you can only extend one class at a time and implement multiple interfaces, but when laying hands on software engineering, I would rather suggest a problem specific solution not generally answerable. By the way, it is good OO practice, not to extend concrete classes/only extend abstract classes to prevent unwanted inheritance behavior - there is no such thing as an "animal" and no use of an animal object but only concrete animals.
In Java 8 and later, you could use default methods to achieve a sort of C++-like multiple inheritance.
You could also have a look at this tutorial which shows a few examples that should be easier to start working with than the official documentation.
It is safe to keep a horse in a stable with a half door, as a horse cannot get over a half door. Therefore I setup a horse housing service that accepts any item of type horse and puts it in a stable with a half door.
So is a horse like animal that can fly even a horse?
I used to think a lot about multiple inheritance, however now that I have been programming for over 15 years, I no longer care about implementing multiple inheritance.
More often than not, when I have tried to cope with a design that pointed toward multiple inheritance, I have later come to release that I had miss understood the problem domain.
OR
If it looks like a duck and quacks like a duck but it needs
batteries, you probably have the wrong abstraction.
Java does not have a Multiple inheritance problem, since it does not have multiple inheritance. This is by design, in order to solve the real multiple inheritance problem (The diamond problem).
There are different strategies for mitigating the problem. The most immediately achievable one being the Composite object that Pavel suggests (essentially how C++ handles it). I don't know if multiple inheritence via C3 linearization (or similar) is on the cards for Java's future, but I doubt it.
If your question is academic, then the correct solution is that Bird and Horse are more concrete, and it is false to assume that a Pegasus is simply a Bird and a Horse combined. It would be more correct to say that a Pegasus has certain intrinsic properties in common with Birds and Horses (that is they have maybe common ancestors). This can be sufficiently modeled as Moritz' answer points out.
I think it depends very much on your needs, and how your animal classes are to be used in your code.
If you want to be able to make use of methods and features of your Horse and Bird implementations inside your Pegasus class, then you could implement Pegasus as a composition of a Bird and a Horse:
public class Animals {
public interface Animal{
public int getNumberOfLegs();
public boolean canFly();
public boolean canBeRidden();
}
public interface Bird extends Animal{
public void doSomeBirdThing();
}
public interface Horse extends Animal{
public void doSomeHorseThing();
}
public interface Pegasus extends Bird,Horse{
}
public abstract class AnimalImpl implements Animal{
private final int numberOfLegs;
public AnimalImpl(int numberOfLegs) {
super();
this.numberOfLegs = numberOfLegs;
}
#Override
public int getNumberOfLegs() {
return numberOfLegs;
}
}
public class BirdImpl extends AnimalImpl implements Bird{
public BirdImpl() {
super(2);
}
#Override
public boolean canFly() {
return true;
}
#Override
public boolean canBeRidden() {
return false;
}
#Override
public void doSomeBirdThing() {
System.out.println("doing some bird thing...");
}
}
public class HorseImpl extends AnimalImpl implements Horse{
public HorseImpl() {
super(4);
}
#Override
public boolean canFly() {
return false;
}
#Override
public boolean canBeRidden() {
return true;
}
#Override
public void doSomeHorseThing() {
System.out.println("doing some horse thing...");
}
}
public class PegasusImpl implements Pegasus{
private final Horse horse = new HorseImpl();
private final Bird bird = new BirdImpl();
#Override
public void doSomeBirdThing() {
bird.doSomeBirdThing();
}
#Override
public int getNumberOfLegs() {
return horse.getNumberOfLegs();
}
#Override
public void doSomeHorseThing() {
horse.doSomeHorseThing();
}
#Override
public boolean canFly() {
return true;
}
#Override
public boolean canBeRidden() {
return true;
}
}
}
Another possibility is to use an Entity-Component-System approach instead of inheritance for defining your animals. Of course this means, that you will not have individual Java classes of the animals, but instead they are only defined by their components.
Some pseudo code for an Entity-Component-System approach could look like this:
public void createHorse(Entity entity){
entity.setComponent(NUMER_OF_LEGS, 4);
entity.setComponent(CAN_FLY, false);
entity.setComponent(CAN_BE_RIDDEN, true);
entity.setComponent(SOME_HORSE_FUNCTIONALITY, new HorseFunction());
}
public void createBird(Entity entity){
entity.setComponent(NUMER_OF_LEGS, 2);
entity.setComponent(CAN_FLY, true);
entity.setComponent(CAN_BE_RIDDEN, false);
entity.setComponent(SOME_BIRD_FUNCTIONALITY, new BirdFunction());
}
public void createPegasus(Entity entity){
createHorse(entity);
createBird(entity);
entity.setComponent(CAN_BE_RIDDEN, true);
}
you can have an interface hierarchy and then extend your classes from selected interfaces :
public interface IAnimal {
}
public interface IBird implements IAnimal {
}
public interface IHorse implements IAnimal {
}
public interface IPegasus implements IBird,IHorse{
}
and then define your classes as needed, by extending a specific interface :
public class Bird implements IBird {
}
public class Horse implements IHorse{
}
public class Pegasus implements IPegasus {
}
Ehm, your class can be the subclass for only 1 other, but still, you can have as many interfaces implemented, as you wish.
A Pegasus is in fact a horse (it is a special case of a horse), which is able to fly (which is the "skill" of this special horse). From the other hand, you can say, the Pegasus is a bird, which can walk, and is 4legged - it all depends, how it is easier for you to write the code.
Like in your case you can say:
abstract class Animal {
private Integer hp = 0;
public void eat() {
hp++;
}
}
interface AirCompatible {
public void fly();
}
class Bird extends Animal implements AirCompatible {
#Override
public void fly() {
//Do something useful
}
}
class Horse extends Animal {
#Override
public void eat() {
hp+=2;
}
}
class Pegasus extends Horse implements AirCompatible {
//now every time when your Pegasus eats, will receive +2 hp
#Override
public void fly() {
//Do something useful
}
}
Interfaces don't simulate multiple inheritance. Java creators considered multiple inheritance wrong, so there is no such thing in Java.
If you want to combine the functionality of two classes into one - use object composition. I.e.
public class Main {
private Component1 component1 = new Component1();
private Component2 component2 = new Component2();
}
And if you want to expose certain methods, define them and let them delegate the call to the corresponding controller.
Here interfaces may come handy - if Component1 implements interface Interface1 and Component2 implements Interface2, you can define
class Main implements Interface1, Interface2
So that you can use objects interchangeably where the context allows it.
So in my point of view, you can't get into diamond problem.
As you will already be aware, multiple inheritance of classes in Java is not possible, but it's possible with interfaces. You may also want to consider using the composition design pattern.
I wrote a very comprehensive article on composition a few years ago...
https://codereview.stackexchange.com/questions/14542/multiple-inheritance-and-composition-with-java-and-c-updated
Define interfaces for defining the capabilities. You can define multiple interfaces for multiple capabilities. These capabilities can be implemented by specific Animal or Bird.
Use inheritance to establish relationships among classes by sharing non-static and non-public data/methods.
Use Decorator_pattern to add capabilities dynamically. This will allow you to reduce number of inheritance classes & combinations.
Have a look at below example for better understanding
When to Use the Decorator Pattern?
To reduce the complexity and simplify the language, multiple inheritance is not supported in java.
Consider a scenario where A, B and C are three classes. The C class inherits A and B classes. If A and B classes have same method and you call it from child class object, there will be ambiguity to call method of A or B class.
Since compile time errors are better than runtime errors, java renders compile time error if you inherit 2 classes. So whether you have same method or different, there will be compile time error now.
class A {
void msg() {
System.out.println("From A");
}
}
class B {
void msg() {
System.out.println("From B");
}
}
class C extends A,B { // suppose if this was possible
public static void main(String[] args) {
C obj = new C();
obj.msg(); // which msg() method would be invoked?
}
}
To solve the problem of mutiple inheritance in Java → interface is used
J2EE (core JAVA) Notes By Mr. K.V.R Page 51
Day - 27
Interfaces are basically used to develop user defined data types.
With respect to interfaces we can achieve the concept of multiple inheritances.
With interfaces we can achieve the concept of polymorphism, dynamic binding and hence we can improve the performance of a JAVA program in
turns of memory space and execution time.
An interface is a construct which contains the collection of purely
undefined methods or an interface is a collection of purely abstract
methods.
[...]
Day - 28:
Syntax-1 for reusing the features of interface(s) to class:
[abstract] class <clsname> implements <intf 1>,<intf 2>.........<intf n>
{
variable declaration;
method definition or declaration;
};
In the above syntax clsname represents name of the class which is
inheriting the features from ‘n’ number of interfaces. ‘Implements’ is
a keyword which is used to inherit the features of interface(s) to a
derived class.
[...]
Syntax-2 inheriting ‘n’ number of interfaces to another interface:
interface <intf 0 name> extends <intf 1>,<intf 2>.........<intf n>
{
variable declaration cum initialization;
method declaration;
};
[...]
Syntax-3:
[abstract] class <derived class name> extends <base class name> implements <intf 1>,<intf 2>.........<intf n>
{
variable declaration;
method definition or declaration;
};
Problem not solved. To sufficiently model this out and to prevent code replication you'd either need multiple inheritance or mixins. Interfaces with default functions are not sufficient because you cannot hold members in interfaces.
Interface modeling leads to code replication in subclasses or statics, which is both evil.
All you can do is to use a custom construction and split it up in more components and compose it all together...
toy language
I have a method in a class say
// super class
public class Car{
public void printMe(Car c){
if(c instanceof BMW){
Utility.printString("Bmw");
}else if(em instanceof VOLVO){
Utility.printString("Volvo");
}else if(em instanceof AUDI){
Utility.printString("Audi");
}else {
Utility.printString("Kia");
}
}
// sub classes
public class Bmw extends Car{
}
public class Volvo extends Car{
}
public class Audi extends Car{
}
public class Kia extends Car{
}
}
Now here i have a different class that loops through a list of Cars and print the correct statement according to the type of the Car
public class AccessCars{
ArrayLists<Car> carsList = listOfcars();
for(Car car: carsList){
car.PrintMe(car);
}
}
In the loop above i call the printMe(Car c) method on car en give car as an argument. Is is legal to do that? And if not, what is the best way of doing it?
thanks for your answer
a better way will be:
public abstract class Car {
public abstract void printMe();
}
public class Audi {
#Override
public void printMe() {
Utility.printString("Audi");
}
this is the OOP way to do it - using polymorphism
note that Car is implicit argument for printMe()
I would advise against polymorphism in this case -- every class prints out a string in the same way. The behavior is constant -- only the value printed varies. As such, the correct approach (IMO) is a variable that's printed out by printMe, and each derived class just initializes the variable appropriately.
It's legal, but not very good design. Perhaps a better approach is to define an abstract method Car.getModel() and implement it in each subclass to return the appropriate value. After all, you don't want to have to change the code for Car every time you add a new subclass.
Um, you can do that ... but I think you're missing the point of inheritance and overriding methods:
public class Car{
void printMe()
{
System.out.println("I'm a Car!");
}
}
public class Audi extends Car{
void printMe()
{
System.out.println("I'm an Audi!");
}
}
for(Car car: carsList){
car.PrintMe()
}
You get the overriden methods. Each car will print its name.
That being said, this is a silly example just to show how that works.
You'd really declare the Car class abstract and have printMe() be abstract, unless you had some reason to ever instantiate Car directly.
It's generally not acceptable to do this; since you already have "specialized" classes, why not put the printMe method in these classes? In case you want to enforce the subclasses have their own version of printMe, just make the printMe method in the super-class as abstract.
On a side note, another thing you might be interested would be a Visitor pattern:
In object-oriented programming and
software engineering, the visitor
design pattern is a way of separating
an algorithm from an object structure
it operates on. A practical result of
this separation is the ability to add
new operations to existing object
structures without modifying those
structures. It is one way to easily
follow the open/closed principle.
Definetly not OK, to do it.
I would define an abstract method called .Print() on the super class in such a way every subclass of Car must override it, and have your own way of Printing. Just like many samples above!
It is legal, however, not best of practice.
instanceof is a heavy operation on runtime environment and as such should be avoided if possible. This is not needed here, as every Car instance do the same thing - print itself. Consider this example:
public class Car {
// do some great stuff here...
public abstract String printMe();
}
public class Audi extends Car {
// do some great stuff here...
public String printMe() {
return "Audi rocks!";
}
}
// same for the other car models...
now iterate on the Car collection and run printMe for each.