Related
I am learning how to use the Factory pattern for creating objects in Java. I want to create classes to manage Cars. A car can either be small or large. I created an interface that defines the methods to be implemented by an implementing class. An abstract class implements some of the common methods of the interface shared by small and large cars. The concrete SmallCar and LargeCar classes implement the remaining methods of the abstract class.
THE CAR INTERFACE
public interface Car {
String getRegistrationNumber();
void drive();
}
THE ABSTRACT CAR CLASS IMPLEMENTS CAR INTERFACE
public abstract class AbstractCar implements Car {
private final RegistrationNumber regNumber;
private boolean tankFull = true;
public AbstractCar(RegistrationNumber regNumber) {
this.regNumber = regNumber;
}
#Override
public final String getregistrationNumber() {
return regNumber.toString();
}
/**This method is not defined in the implemented Car interface. I added it to
*the abstract class because I want subclasses of these abstract class
*to have this method*/
public boolean isTankFull() {
return tankFull;
}
}
SMALL CAR EXTENDS ABSTRACT CLASS
public final class SmallCar extends AbstractCar {
public SmallCar(RegistrationNumber regNum) {
super(regNum);
}
#Override
public void drive() {
//implemented here
}
}
FACTORY CLASS:
This class is responsible for creating instances of a particular type of car.
public final class CarFactory {
public static Car createCar(String carType, RegistrationNumber regNum) {
Car car = null;
if (carType.equals("Small") {
car = new SmallCar(regNum);
}
return car;
}
MAIN METHOD
RegistrationNumber regNum = new RegistrationNumber('a', 1234);
Car c = CarFactory.createCar("Small", regNum);
c.getRegistrationNumber(); //this works
c.isTankFull(); //this instance of Car cannot access the isTankFull method defined on the abstract class. The method is not defined on the Car interface though. I do not understand why.
The challenge is that the instance of Car can access every other method defined on the Car interface but it cannot access the isTankFull() method defined on the abstract class but not defined on the interface. I hope my explanation is clear enough.
The reason why you can't see the method there is because your c object is declared as a Car interface. Granted, when it comes out of your factory method, it is a SmallCar, but your variable there is only the interface. You could either change your declaration to AbstractCar c = CarFactory.createCar("SmallCar", regnum);.
Another way you could accomplish this while working with the interface would be to cast your c object to an AbstractCar when trying to access methods that are not on the interface, however you need to be careful as there is always the possibility that your factory could return an object that implements Car, but not AbstractCar.
if (c instanceof AbstractCar) {
((AbstarctCar)c).isTankFull();
}
Of course, the other easy solution would be to add the method to the interface, though that would remove the teaching opportunity from this question.
The good solution is to put your isTankFull() on the interface. It makes sense as any car implementing Car would need access to isTankFull().
The question is: are you creating any Car that will not be able to answer the question isTankFull? If so, then moving isTankFull to the interface will not make sense.
Another solution (if you don't want your isTankFull() to be on the interface), is to cast your Car to the appropriate type:
if (c instanceof AbstractCar) {
((AbstractCar)c).isTankFull();
}
An interface is a contract (or a protocol) that you made with the users of the classes that implement it. So you have to ask to yourself if any Car should expose the information isTankFull (i.e. should respond to message isTankFull). If the answer is 'yes', then the method isTankFull must be added to the interface.
Looking at your code, it seems that the class AbstractCar is only a utility class. Then, the method isTankFull should be lift up to interface, or it should be made at least protected.
On the other hand you have to ask yourself if your client code, i.e. main method, really needs a generic Car, or if it needs instead a specific kind of car, such as a SmallCar.
Finally, rember that the use of interface lets you minimize dependency between your components.
What is the advantage of writing:
Bicycle bike = new RoadBike(...);
instead of
RoadBike bike = new RoadBike(...);
Assuming RoadBike extends Bicycle of course.
I ask because even if I write
RoadBike bike = new RoadBike(...);
I can still use all the methods in Bicycle because of the extension, so what is the point of writing it the other way?
Thanks!
If Bicycle were an interface, it would allow you to just pass around that interface and make your methods more "generic" or "polymorphic".
If you had another class, StreetBike,(and it implemented the Bicycle Interface) you could use that class and RoadBike to say call method 'ride' and each class would ride differently based on the implementation.
Public Interface Bicycle {
public ride();
}
public StreetBike implements Bicycle{
public ride(){
System.out.println("I am riding on the street");
}
}
public RoadBike implements Bicycle{
public ride(){
System.out.println("I am riding on the road");
}
}
Taking it a step further we can use this SIMPLE example, but I think it gets the point across
//PERSON POJO
public Person {
//properties
public rideBike(Bicycle bike){
bike.ride(); //could be StreetBike or RoadBike, depends on what you pass in. That's the power of it.
}
}
The clearest way to express polymorphism is via an abstract base class (or interface)
public abstract class Bicycle
{
...
public abstract void ride();
}
This class is abstract because the ride() method is not defined for Bicycle. It will be defined for the subclasses RoadBike and MountainBike. Also, Bicycle is an abstract concept . It’s got to be one or the other.
So we defer the implementation by using the abstract class.
public class RoadBike extends Bicycle
{
...
#Override
public void ride()
{
System.out.println("RoadBike");
}
}
and
public class MountainBike extends Bicycle
{
...
#Override
public void ride()
{
System.out.println("MountainBike");
}
}
Now we can difference by calling Bicycle at runtime base class Bicycle but due to run time binding respective subclass methods will be invoked .
public static void main(String args)
{
ArrayList<Bicycle> group = new ArrayList<Bicycle>();
group.add(new RoadBike());
group.add(new MountainBike());
// ... add more...
// tell the class to take a pee break
for (Bicycle bicycle : group) bicycle.ride();
}
Running this would yield:
RoadBike
MountainBike
...
Hope this will clear you what the difference is !
The advantage is that Bicycle reference is more general and can refer to any object which has Bicycle in its inheritance hierarchy for example MountainBike. It offers more flexibility and does not binds you to concrete implementation. This is one of the basic principles in OOP. That said, there are some cases, like when used in short method when using Bicycle or RoadBikemakes no difference. Also there is the aspect of invoking overloaded methods which is determined by reference type at compile time (depending on the reference type, different method might be called even thought they point to the same object) but having those kinds of overlaoded methods is not advised.
You might get better explanation here.
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
What's the point of using "abstract methods"? An abstract class cannot be instantiated, but what about the abstract methods? Are they just here to say "you have to implement me", and if we forget them, the compiler throws an error?
Does it mean something else? I also read something about "we don't have to rewrite the same code", but in the abstract class, we only "declare" the abstract method, so we will have to rewrite the code in the child class.
Can you help me understand it a bit more? I checked the other topics about "abstract class/methods" but I didn't find an answer.
Say you have three printers that you need to write drivers for, Lexmark, Canon, and HP.
All three printers will have the print() and getSystemResource() methods.
However, print() will be different for each printer, and getSystemResource() remains the same for all three printers. You also have another concern, you would like to apply polymorphism.
Since getSystemResource() is the same for all three printers, you can push this up to the super class to be implemented, and let the subclasses implement print(). In Java, this is done by making print() abstract in the super class. Note: when making a method abstract in a class, the class itself needs to be abstract as well.
public abstract class Printer{
public void getSystemResource(){
// real implementation of getting system resources
}
public abstract void print();
}
public class Canon extends Printer{
public void print(){
// here you will provide the implementation of print pertaining to Canon
}
}
public class HP extends Printer{
public void print(){
// here you will provide the implementation of print pertaining to HP
}
}
public class Lexmark extends Printer{
public void print(){
// here you will provide the implementation of print pertaining to Lexmark
}
}
Notice that HP, Canon and Lexmark classes do not provide the implementation of getSystemResource().
Finally, in your main class, you can do the following:
public static void main(String args[]){
Printer printer = new HP();
printer.getSystemResource();
printer.print();
}
Besides the reminder that you have to implement it, the big advantage is that anyone who references the object by its abstract class type (including this in the abstract class itself) can use the method.
For instance, let's say we have a class responsible for taking state and manipulating it in some way. The abstract class is going to be responsible for getting the input, converting it to a long (for instance) and combining that value with the previous value in some way -- that "some way" is the abstract method. The abstract class may look something like:
public abstract class StateAccumulator {
protected abstract long accumulate(long oldState, long newState);
public handleInput(SomeInputObject input) {
long inputLong = input.getLong();
state = accumulate(state, inputLong);
}
private long state = SOME_INITIAL_STATE;
}
Now you can define an addition accumulator:
public class AdditionAccumulator extends StateAccumulator {
#Override
protected long accumulate(long oldState, long newState) {
return oldState + newState;
}
}
Without that abstract method, the base class would have no way to say "handle this state somehow." We don't want to provide a default implementation in the base class, though, because it wouldn't mean much -- how do you define a default implementation for "someone else will implement this"?
Note that there's more than one way to skin a cat. The strategy pattern would involve declaring an interface that declares the accumulate pattern, and passing an instance of that interface to the no-longer-abstract base class. In lingo terms, that's using composition instead of inheritance (you've composed an addition aggregator out of two objects, an aggregator and an adder).
Abstract classes are classes that contain one or more abstract methods. An abstract method is a method that is declared, but contains no implementation. Abstract classes may not be instantiated, and require subclasses to provide implementations for the abstract methods. Let's look at an example of an abstract class, and an abstract method.
Suppose we were modeling the behavior of animals, by creating a class hierachy that started with a base class called Animal. Animals are capable of doing different things like flying, digging and walking, but there are some common operations as well like eating and sleeping and making noise. Some common operations are performed by all animals, but in a different way as well. When an operation is performed in a different way, it is a good candidate for an abstract method (forcing subclasses to provide a custom implementation). Let's look at a very primitive Animal base class, which defines an abstract method for making a sound (such as a dog barking, a cow mooing, or a pig oinking).
public abstract Animal {
public void sleep{
// sleeping time
}
public void eat(food)
{
//eat something
}
public abstract void makeNoise();
}
public Dog extends Animal {
public void makeNoise() {
System.out.println("Bark! Bark!");
}
}
public Cow extends Animal {
public void makeNoise() {
System.out.println("Moo! Moo!");
}
}
Note that the abstract keyword is used to denote both an abstract method, and an abstract class. Now, any animal that wants to be instantiated (like a dog or cow) must implement the makeNoise method - otherwise it is impossible to create an instance of that class. Let's look at a Dog and Cow subclass that extends the Animal class.
Now you may be wondering why not declare an abstract class as an interface, and have the Dog and Cow implement the interface. Sure you could - but you'd also need to implement the eat and sleep methods. By using abstract classes, you can inherit the implementation of other (non-abstract) methods. You can't do that with interfaces - an interface cannot provide any method implementations.
In simple word an interface should contain all abstract method but no implementation of method or we can’t define non abstract method in interface, in interface all the method should be abstract but in abstract class we can define both abstract and non abstract method, so for defining non abstract method we don’t have to define another class to implement the behavior of same object this is the advantage of abstract class over interface.
The abstract methods merely define a contract that derived classes must implement. It's is the way how you ensure that they actually always will.
So let's take for example an abstract class Shape. It would have an abstract method draw() that should draw it. (Shape is abstract, because we do not know how to draw a general shape) By having abstract method draw in Shape we guarantee that all derived classed, that actually can be drawn, for example Circle do implement draw. Later if we forget to implement draw in some class, that is derived from Shape, compiler will actually help as giving an error.
Simply speaking, declaring a class to be "abstract", you are enforcing a "contract" for the child classes which inherit it, so it provides a good way to maintain the "contract".
If all an abstract does is declare abstract methods, you are correct, it's a bit silly, and an interface would likely be superior.
But often an abstract class implements some (maybe even all) of the methods, leaving only a few as abstract. For example, AbstractTableModel. This saves rewriting a lot of code.
Another "advantage" over an interface is that an abstract class can declare fields for subclasses to use. So, if you are pretty sure that any reasonable implementation would have a String named uniqueID, you could declare it, plus relevant getters/setters, in the abstract class, saving some typing later.
Abstract methods must be overriden by any subclass that will not be abstract.
So, for example you define an abstract class Log and you force the subclasses to override that method:
public abstract class Log{
public void logError(String msg){
this.log(msg,1)
}
public void logSuccess(String msg){
this.log(msg,2)
}
public abstract void log(String msg,int level){}
}
public class ConsoleLog{
public void log(String msg,int level){
if(level=1){
System.err.println(msg)
}else{
System.out.println(msg)
}
}
}
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.