I would like to require classes that extend my abstract class A to provide an enumerated type. I don't need to constrain the type itself, I just want to ensure that they provide some enumerated type. For example, I have an abstract class Animal and I want to ensure that every Animal has a set of behaviors. I don't need to constrain these behaviors or create a master list in any way; I just want to ensure that all Animals return a list of symbolic behaviors.
Ideally, I would like to say:
public abstract class Animal {
public List<Enum> getBehaviors();
}
but this won't compile cleanly.
Any ideas? Would it be better to approach this via Generics?
Ok, I'm going to expand my comment a bit here.
If you want to have your getBehaviors() method return a list of behaviors for a particular animal, making the method signature declare that a List<Enum<?>> is returned does nothing to help you. A client who gets your List<Enum<?>> from that method isn't able to do anything useful with it (who knows what it is?). The restriction also doesn't do anything to help ensure that the type of objects the behaviors list contains are actually "behaviors", whatever that means to in the context of your application. They could be days of the week, months of the year or just about anything!
What I'm guessing is that you have some enums like DogBehavior (with constants like BARK, BITE, etc.) and you want to ensure that only such behaviors are allowed in the list. The fact that these behaviors are collected in enums is an implementation detail. What you should do is introduce a common interface that designates something as a Behavior. If there aren't any specific methods associated with a Behavior, it could just be a marker interface (that defines no methods). Otherwise, you might want it to have some methods, like such:
public interface Behavior {
public String getName();
public void doBehavior();
// etc.
}
You could then have some enums that implement this interface:
public enum DogBehavior implements Behavior {
BARK("Bark") {
public void doBehavior() {
// bark
}
},
// etc.
private final String name;
DogBehavior(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Then, 'Animal' might look like:
public abstract class Animal {
public abstract List<Behavior> getBehaviors();
}
Which makes a lot more sense to me.
I'm a bit confused - if you want to require all Animals to export a set of behaviors, then ideally your goal would be to be able to write something like this:
Animal a = /* .. create some subtype of Animal .. */
List</* ?? */> behaviors = a.getBehaviors();
The problem here is that if you want each Animal create its own enumerated type for behaviors, you have no unified way of talking about those behaviors unless you explicitly specify some type that represents them. In other words, you can't fill in the /* ?? */ above unless in the Animal interface you provide a type that all Animal behaviors should be related to.
One option would be to define a class like this one:
public final class Behavior {
private final String name;
public Behavior(String name) {
this.name = name;
}
public String getBehaviorName() {
return name;
}
/* ... etc. ... */
}
Then, you could have each Animal type define getBehaviors() so that it returns a list of Behavior objects. This gives you a type-safe framework for discussing behaviors, and potentially the ability to add more complex actions for each behavior.
2 things I see wrong.
First, you need to mark that method abstract. You didn't provide an implementation.
Second, the Enum should be parameterized if you don't want a warning. Enum<?> should be enough if you don't need to restrict the Enum further.
However, as others have noted, this probably is NOT what you want. An Enum of "behaviors" is useless to you. They have no functionality once returned from getBehaviors(). You could iterate through them and list them, but that's worth nothing more than a List<String>.
I would think that you want a List<Behavior> where Behavior is an interface that DOES something for you.
EDIT: ColinD above beat me to the punch on the same point.
public abstract class Animal {
public List<? extends Enum<?>> getBehaviors();
}
Related
I have been studying abstract methods lately and I can't understand why do we need them?
I mean, after all, we are just overriding them. Do you know its just a declaration? Why do we need them?
Also, I tried understanding this from the internet and everywhere there's an explanation like imagine there's an abstract class human then there're its subclasses disabled and not disabled then the abstract function in human class walking() will contain different body or code. Now what I am saying is why don't we just create a function in the disabled and not disabled subclasses instead of overriding. Thus again back to the question in the first paragraph. Please explain it.
One of the most obvious uses of abstract methods is letting the abstract class call them from an implementation of other methods.
Here is an example:
class AbstractToy {
protected abstract String getName();
protected abstract String getSize();
public String getDescription() {
return "This is a really "+getSize()+" "+getName();
}
}
class ToyBear extends AbstractToy {
protected override String getName() { return "bear"; }
protected override String getSize() { return "big"; }
}
class ToyPenguin extends AbstractToy {
protected override String getName() { return "penguin"; }
protected override String getSize() { return "tiny"; }
}
Note how AbstractToy's implementation of getDescription is able to call getName and getSize, even though the definitions are in the subclasses. This is an instance of a well-known design pattern called Template Method.
The abstract method definition in a base type is a contract that guarantees that every concrete implementation of that type will have an implementation of that method.
Without it, the compiler wouldn't allow you to call that method on a reference of the base-type, because it couldn't guarantee that such a method will always be there.
So if you have
MyBaseClass x = getAnInstance();
x.doTheThing();
and MyBaseClass doesn't have a doTheThing method, then the compiler will tell you that it can't let you do that. By adding an abstract doTheThing method you guarantee that every concrete implementation that getAnInstance() can return has an implementation, which is good enough for the compiler, so it'll let you call that method.
Basically a more fundamental truth, that needs to be groked first is this:
You will have instances where the type of the variable is more general than the type of the value it holds. In simple cases you can just make the variable be the specific type:
MyDerivedClassA a = new MyDerivcedClassA();
In that case you could obviously call any method of MyDerivedClassA and wouldn't need any abstract methods in the base class.
But sometimes you want to do a thing with any MyBaseClass instance and you don't know what specific type it is:
public void doTheThingsForAll(Collection<? extends MyBaseClass> baseClassReferences) {
for (MyBaseClass myBaseReference : baseClassReferences) {
myBaseReference.doTheThing();
}
}
If your MyBaseClass didn't have the doTheThing abstract method, then the compiler wouldn't let you do that.
To continue with your example, at some point you might have a List of humans, and you don't really care whether they are disabled or not, all you care about is that you want to call the walking() method on them. In order to do that, the Human class needs to define a walking() method. However, you might not know how to implement that without knowing whether the human is or isn't disabled. So you leave the implementation to the inheriting classes.
There are some examples of how you'd use this in the other answers, so let me give some explanation of why you might do this.
First, one common rule of Object Oriented Design is that you should, in general, try to program to interfaces rather than specific implementations. This tends to improve the program's flexibility and maintainability if you need to change some behavior later. For example, in one program I wrote, we were writing data to CSV files. We later decided to switch to writing to Excel files instead. Programming to interfaces (rather than a specific implementation) made it a lot easier for us to make this change because we could just "drop in" a new class to write to Excel files in place of the class to write to CSV files.
You probably haven't studied this yet, but this is actually important for certain design patterns. A few notable examples of where this is potentially helpful are the Factory Pattern, the Strategy Pattern, and the State Pattern.
For context, a Design Pattern is a standard way of describing and documenting a solution to a known problem. If, for example, someone says "you should use the strategy pattern to solve this problem," this makes the general idea of how you should approach the problem clear.
Because sometimes we need a method that should behave differently in its instances.
For example, imagine a class Animal which contains a method Shout.
We are going to have different instances of this Animal class but we need to implement the method differently in some cases like below:
class Animal:
/**
different properties and methods
which are shared between all animals here
*/
...
method shout():
pass
class Dog extends Animal:
method shout():
makeDogVoice()
class Cat extends Animal:
method shout():
makeCatVoice()
dog = new Animal
cat = new Animal
dog.shout()
cat.shout()
So dog shouts like dogs, and cat shouts like cats! Without implementing the shared behaviors twice
There is a different behavior of shouting in these instances. So we need abstract classes.
Suppose you don't know about implementation and still want to declare a method then we can do that with the help of abstract modifier and making it an abstract method. For abstract method only declaration is available but not the implementation. Hence they should end with ;
Example:
public abstract void m1(); // this is correct
public abstract void m1(){ ... } // this is wrong
Advantage: By declaring abstract method in parent class we can provide guideline to child classes such that which methods are compulsory to implement.
Example:
abstract class Vehicle{
abstract int getNoOfWheels();
}
Class Bus extends Car{
public int getNoOfWheels(){
return 4;
}
}
If you want the short answer, think of this:
You have an abstract class Car.
You implement 2 classes that extend it, Ferrari and Mercedes.
Now:
What if you did one of the following, for the method drive(), common to all cars:
1) changed the visibility of the method,
2) changed the name of the method from driving to Driving,
3) changed the return type, from a boolean to an int
Think about it. It might not seem to make any difference right, because they are different implementations?
Wrong!
If I am iterating through an array of cars, I would have to call a different method for each type of car, thereby making this implementation of abstract useless.
Abstract classes are there to group classes with a common template, that share common properties. One way this helps would be the looping over the array:
Abstract methods ensure that all cars declare the same method,
and therefore, any object of a subclass of Car will have the method drive(), as defined in the abstract class, making the for loop mentioned easy to implement.
Hope this helps.
I just came into a problem with designing an interface whose methods may have variable numbers of input arguments.
public interface FoobarSerialization<T> {
Foobar serialize(T obj);
}
The problem is, for the classes that implement this interface, they require different numbers of input arguments.
public class FoobarA implements FoobarSerialization<FoobarA> {
#Override
public Foobar serialize(FoobarA obj, int bar) {
//...
}
}
public class FoobarB implements FoobarSerialization<FoobarB> {
#Override
public Foobar serialize(FoobarB obj, Date date, String str) {
//...
}
}
Is there a good design or any genuine way to solve this problem? I know the method in the interface can be declared as:
Foobar serialize(T... obj);
But I'm not sure if this was a good practice to design an interface like this.
Any thought?
Update: My intention of using an interface came from the collection of classes that need to be serialized and deserialized for different purposes. They serve as components under the same domain. But their serialization methods are quite different, especially considering their dependencies on objects and services that don't share any common features nor classes.
I guess the right question to ask here is: in terms of design, what's the best approach when there exits a set of classes which share the same behaviors (serialize, deserialize, doSomething, etc) but have different input args?
Composition pattern to the rescue.
In your particular case I would create interface which accepts just 1 parameter:
public interface Serializer<T> {
Foobar serialize(T object);
}
Now, if you need to serialize several fields, you just create an object which has all fields you need to serialize:
class FoobarBundle {
String stringField;
int intField;
byte[] arrayField;
/* ... */
}
And write bunch of serializers: FoobarBundleSerializer, StringSerializer, IntegerSerializer, ByteArraySerializer. In the end combine all serializers in FoobarBundleSerializer like that:
class FoobarBundleSerializer implements Serializer<FoobarBundle> {
StringSerializer stringSerializer;
IntegerSerializer integerSerializer;
ByteArraySerializer byteArraySerializer;
/* constructor here */
#Override
public Foobar serialize(FoobarBundle bundle) {
Foobar foobarString = stringSerializer.serialize(bundle.stringField);
Foobar foobarInteger = integerSerializer.serialize(bundle.intField);
Foobar foobarByteArray = byteArraySerializer.serialize(bundle.byteArrayField);
return combineFoobarSomehow(foobarString, foobarInteger, foobarByteArray);
}
}
Your mileage may vary, but usually confusing use (e.g. same number, but different types of arguments) of methods with the same name should be avoided. Though one can take help of method overloading, it is considered less than desirable. If the list of parameters is manageable, you should name the method differently to avoid ambiguities. See Item 26 in Effective Java 2.
The vararg methods are alright, but in Java, the best practice is to specify at least one concrete argument followed by a variable number of arguments of the same type. This is perhaps not applicable in your case, since there is no vararg syntax for a method like public Foobar serialize(FoobarB obj, Date date, String str);. It might be acceptable to use a syntax like (Object ... objects), but this practice is not considered generally applicable.
Contrast this with a method like printf which can and should be able to output a variable number of arguments of any type (including primitives) to an output stream.
When laying out a class hierarchy, I often find myself frustrated at the gap between being able to encapsulate functionality while also sharing code. Part of the problem, of course, is lack of multiple inheritance, but interfaces help somewhat. The inability to define protected methods on interfaces seems to me to be the bigger issue.
The standard solution seems to be to have a public interface that is implemented by a protected abstract base class. The problem is when we have the following
public interface Foo {
public String getName();
}
abstract protected BaseFoo implements Foo {
abstract protected int getId();
private String name;
protected BaseFoo(String name) {
this.name = name;
}
#Override
public String getName() {
return this.name;
}
}
public class ConcreteFoo extends BaseFoo {
public ConcreteFoo (String name) {
super(name);
}
#Override
protected int getId() {
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
}
// in the foo package with the classes above
public class FooCollection {
private static Map<Integer, Foo> foos = new HashMap();
public static void add(Foo foo) {
synchronized(foos) {
foos.put(foo.getId(), foo); // can't call foo.getId()
}
}
}
// client code, not in the foo package
FooCollection.add(new ConcreteFoo("hello world"));
That is, we return one of our nicely-encapsulated objects to caller, but then any method which gets that object back needs to be able to rely on some internal functionality. That internal functionality cannot be part of the interface (that would break encapsulation), but to make it part of an abstract base class requires us to use casting.
We cannot make Foo an abstract class because other interfaces need to extend it to add optional, orthogonal functionality to a more complex hierarchy than is display here.
What are the standard approaches to this problem? Do you add getId to the Foo interface, even though clients shouldn't use it? Do you perform an unsafe cast to BaseFoo in FooCollection.add? If you check before casting, what do you do when the types don't match, even though they always should for all intents and purposes?
Any information you have on best practices in this sort of situation would be very helpful.
Edit: In case it's not clear, this example is intentionally oversimplified. The key point is that sometimes you return an "interface view" of an object. When that "interface view" is passed back in to a package-specific class, the method it is passed to will likely need to use internal functionality in its implementation. How does one manage that mismatch between internal and public functionality?
Okay, here's a couple of points:
Contrary to popular opinion, inheritance really isn't about sharing code. What you create in an inheritance hierarchy is an organization of things that share some common set of abstract behaviors; it just works out sometimes to have the effect of reusing some code.
The fashion has changed quite a bit in the last few years, so that deep and complicated inheritance hierarchies are no longer considered good form. In general in Java. you should
use aggregation before implementing an interface
use interfaces to express "mix-in" contracts
use inheritance only if the classes describe something that has natural inheritance.
If you really want the effect of multiple inheritance, build implementation classes for your interfaces, and aggregate them.
In particular, by defining your classes with interfaces and implementation classes, you make building tests much easier; if your interface is separate, it's almost trivial to build a mock for that interface.
I don't know about "best" practices, but here are a couple of ideas.
Interfaces are supposed to separate "what is to be done" from "how something is to be done". I don't think getters and setters belong in interfaces. I try to give them more meaningful signatures.
In your case, I see nothing wrong with two interfaces:
public interface Nameable {
String getName();
}
public interface Identifiable {
int getId();
}
Separate the two; force clients to implement only the ones they need. Your decision to make id part of the abstract class is arbitrary. Separating it out and making it explicit can be helpful.
Casting loses all benefit of polymorphism. I don't think that it should be abandoned lightly. If you must move getId() up to the interface, do so. If you can avoid it by different choices, do so.
"Best" depends on your context. Your simple example might not be true in all cases.
Today i heard from my friend, that encapsulation is not only achieving information hiding but also abstraction. How does it achieve?
public class employee {
private String name;
private int id;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
The above example achieves encapsulation where i am allowing the class to access my public method rather than private members, but where does the abstraction come into picture here? Can anyone explain me on abstraction in a bit clear manner.
There's two different things, information hiding and abstraction.
Information hiding makes abstraction possible, but it is something different. For example, using your code
public class employee {
private String name;
private int id;
public void setName(String name) {
this.name = name;
}
public String getName(){
return name;
}
}
The id field is actually hidden. This allows one to handle ids in a manner that is decoupled from the rest of the program. Your name field is actually hidden too, as you don't access the name field directly, but the code in getName and setName does.
Once you hide the structure of the data from the rest of the code, forcing access through methods, it is possible to create a number of replaceable implementations of an item. For example, an employee is a conceptual kind of person, so you could rewrite the above like so:
public interface Person {
public abstract String getName();
}
public class Employee implements Person {
private String name;
private int id;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Now your code can deal with the Employee as a Person. After rewriting the rest of the code that doesn't explicitly deal with Employees to deal with Persons, you could implement other kinds of Persons and leverage the non-Employee specific tasks that are now Person tasks.
public Customer implements Person {
private String name;
private integer moneySpent;
public String getName() {
return name;
}
}
So a person searching routine, as long as it only indexes Person objects can now include searches of both Employees and Customers. This is because the code dealing with Person objects is actually dealing with a higher level abstraction that both Employee and Customer objects share.
When dealing with Objects on an abstract level, the names of the methods are shared across the abstraction; but, the actual code executed depends on the unmentioned underlying type of the object. In other words, if you ask a Person (who happens to be an employee) getName() then it will respond with the Employee.getName() function, while a Customer will respond with a Customer.getName() function. Since the code calling getName() is operating on Persons it has no idea which type of person it will be handling, but the apparent change in behavior (the selection of the right block of code on a per-object basis) still happens. This phenomena is known as Polymorphisim, and if you are first hitting these concepts, you'll hear Polymorphisim as a word used a lot.
An example of polymorpic behavior:
public interface Animal {
public abstract String makeSound();
}
public class Cow implements Animal {
public String makeSound() {
return "Moo Moo!";
}
}
public class Dog implements Animal {
public String makeSound() {
return "Ruff Ruff!";
}
}
public class Sheep implements Animal {
public String makeSound() {
return "Baa Baa!";
}
}
// this class demonstrates the polymorphic behavior
public class Farm {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Cow());
animals.add(new Sheep());
animals.add(new Dog());
for (Animal animal : animals) {
// this is where the polymorphisim occurs
// each animal will make a different sound
// because the makeSound method is getting
// bound to different blocks of code based
// on the exact type of animal class hiding
// under the Animal abstraction.
System.out.println(animal.makeSound());
}
}
}
expected output:
Moo Moo!
Baa Baa!
Ruff Ruff!
even though we never explicitly changed classes, and we never explicitly changed methods. It was the binding of the abstract method to the explicit subclass that was changing, which is something that only happens in systems that support polymorphisim.
# John your friend is right by implementing the encapsulation you also achieve abstraction.
public class employee {
private String name;
private int id;
public void setName(String name){
name= name+"something that you want to edit";
this.name = name; }
public String getName(){
return name; }
}
in this way you have edited ur set method and hided the details from the user which is nothing but abstraction...
thus by writting getters and setters you hide user to do the unneccessary task...
public void setName(String name){
/*some internal logic suppose in database you want name
*should be added with its id but what user to do with it.*/
this.name = name; }
public String getName(){
/* now suppose you have recieved the name from
*data base it has id but you want user to know only
name then you will write the logic here to show the name.*/
return name; }
I know adding id to name is a stupid example but thats what i can think of right now... but consider for a very big project you many times write code in set(or call other method which modifies the parameters of it) then what...
suppose you get the name but you want to save it in a encrypted form in db, then what.
User dont care about the encryption but yes you have to... because its uneccesary to the user but important to you. So that should be in the code of yours but hidden from the user and thats what is all about abstraction*("HIDING THE UNNECCESARY DETAILS FROM USER")*
EDITED:-Go to the source! Grady Booch says (in Object Oriented Analysis and Design, page 49, second edition):
"Abstraction and encapsulation are complementary concepts: abstraction focuses on the observable behavior of an object... encapsulation focuses upon the implementation that gives rise to this behavior... encapsulation is most often achieved through information hiding, which is the process of hiding all of the secrets of object that do not contribute to its essential characteristics."
from above you can conclude the same
I think he's confusing polymorphism with encapsulation. Polymorphism can help you achieve abstration.
It's mostly encapsulation here, but there is some abstraction as well. By using a method called setName(), code that consumes your class doesn't need to know how you're implementing the operation of "setting a name". For all they know, you're calling out to a webservice and setting it in a database somewhere. Or maybe you're ignoring the parameter entirely and setting the name to "Steven" every time. Those facts are abstracted away from the caller.
I don't think you can prove encapsulation with that particular example. It's more like this:
interface NameService {
String getName();
}
Now, tell me: does a class implementing this interface get the name from a flat file, a database, a nosql store, or someplace else?
Abstraction is all about a concept/model which cannot be realized / instantiated as such.
Abstraction is all about restriction on an object's method/members behaviour to other classes.
Personally I wouldn't say encapsulation is really about abstraction (though I see how it could be taken that way), it's about only permitting a user to see or do what's necessary - they only see an interface to the class, not its inner workings. In your case it's achieved because you're only ever setting or getting the name of the particular class, you never access the name variable directly and never see how it's stored. So you could change the name or type of the name variable to something completely different and the interface to your class would still work and look the same. I guess that could be taken in a sense as an abstraction.
The definitions are loose, but I'd consider polymorphism to fall more into the realms of abstraction, where you decouple the implementation (say, ArrayList) from the interface it inherits (say, List.) That way you just deal with the list interface, and the underlying list could be anything, but that's an implementation detail and because you're an abstract level "above" it, you don't need to worry about it. Of course this is a simplification, sometimes you need to know implementation details for performance reasons or if some operations may not be implemented or allowed on your specific implementation. But from a loose viewpoint (and a pure OO viewpoint) it holds.
Whatever you understand it to be, the most important thing is you understand the logic behind it, why it's a good idea and why it's always better to do things that way (in this case, have fields as private and use getters / setters to access them.)
but where does the abstraction come into picture here?
you've said it yourself: "allowing the class to access my public method rather than private members"
or in other words: allowing other classes to access what they may access, and protecting what they may not.
the abstraction here comes from the public methods, for instance in getName() you don't need to always give the private member value, it could be appended with other value or even it could give totally different thing. it's like saying: "tell me your name, regardless how you'd give it to me". maybe a better example would be a method named getYourWorkDone(). the principle remains the same: "get your work done! how? I don't care how!"
the encapsulation part is from the private members. this class encapsulates those private members so they are grouped to form the class' state.
java official documentation for you to understand when to use interface or abstraction.
Also, I couldn't help notice that you were confused between encapsulation and abstraction so here is a simple difference between them for geekforgeeks website
Encapsulation is data hiding (information hiding) while,
Abstraction is detailed hiding
(implementation hiding).
Encapsulation groups together data and methods that act upon the data, data abstraction deal with exposing the interface to the user and hiding the details of implementation.
It seems encapsulation and abstraction has got everyone confused. If you ask me, those are poles-apart topics and there is absolutely no scope of confusion in this.
abstraction happens when you use "abstract" keyword, and encapsulation happens when you create a class. a good implementation of encapsulation involves making all your data members private.
I wrote a few blog posts that might help you:
Learn how to use an Abstract Class in Object Oriented Design
The Theory of Abstraction
Abstraction is done when you want to hide the data.Whereas encapsulation is done when you want to hide both data and code.That is wrapping both data and code which you implement.
You can implement abstraction by using abstract class or interface.
In abstract class we can either write concrete methods or abstract methods but in interface we can only use abstract methods.
You can implement encapsulation by using access modifiers like public, protected, private.
These access modifiers control the access of your data i.e whether it should be public(can be seen by anyone) or protected(can be accessed only by extended classes) or private(hiding it from everyone).
For example suppose I have a class Vehicle and I wish for a subclass ConvertibleVehicle which has extra methods such as foldRoof(), turboMode(), foldFrontSeats() etc. I wish to instantiate as follows
Vehicle convertible = new ConvertibleVehicle()
so I still have access to common method such as openDoor(), startEngine() etc. How do I designed such a solution?
To clarify my two initial solutions, neither of which I am happy with are:
Have dummy methods foldRoof(), turboMode(), foldFrontSeats() which I override in ConvertibleVehicle only, leaving them to do nothing in other subclasses
Have abstract methods foldRoof(), turboMode(), foldFrontSeats() and force each subclass to provide an implementation even if it will be blank in all instances other than ConvertibleVehicle
The above seem slightly convoluted since they both pollute the base class as I add an increasing number of subclasses each with their own unique functions
After reading some of the responses perhaps there is some type of fundamental flaw in my design. Suppose I have a class VehicleFleet which takes vehicles and instructs them to drive as follows:
public VehicleFleet(Vehicle[] myVehicles) {
for (int i=0; i < myVehicles.length; i++) {
myVehicles[i].drive();
}
}
Suppose this works for dozens of subclasses of Vehicle but for ConvertibleVehicle I also want to fold the roof before driving. To do so I subclass VehicleFleet as follows:
public ConvertibleVehicleFleet(Vehicle[] myVehicles) {
for (int i=0; i < myVehicles.length; i++) {
myVehicles[i].foldRoof();
myVehicles[i].drive();
}
}
This leaves me with a messy function foldRoof() stuck in the base class where it doesn't really belong which is overridden only in the case of ConvertibleVehicle and does nothing in all the other cases. The solution works but seems very inelegant. Does this problem lend itself to a better architecture?
I'm using Java although I would hope that a general solution could be found that will work in any object oriented language and that I will not need to rely upon language specific quirks
Any objects that use Vehicle shouldn't know about ConvertibleVehicle and its specialized methods. In proper loosely coupled object-oriented design Driver would only know about the Vehicle interface. Driver might call startEngine() on a Vehicle, but it's up to subclasses of Vehicle to override startEngine() to handle varying implementations such as turning a key versus pushing a button.
Consider reviewing the following two links which should help to explain this concept:
http://en.wikipedia.org/wiki/Liskov_substitution_principle
http://en.wikipedia.org/wiki/Open/closed_principle
Consider posting a real world problem that you feel leads to the dilemma you describe here and someone will be more than happy to demonstrate a better approach.
I've done this in similar situations.
Option A)
If the specialized operations are part of the same sequence as a base operation ( e.g. ConvertibleVehicle needs to be foldRoof before it can drive ) then just put the specialized operation inside the base operation.
class Vehicle {
public abstract void drive();
}
class ConvertibleVehicle {
public void drive() {
this.foldRoof();
.... // drive
}
private void foldRoof() {
....
}
}
So the effect of driving a fleet will be some of them will fold their roof before being driven.
for( Vehicle v : vehicleFleet ) {
v.drive();
}
The specialized method is not exposed in the object public interface but is called when needed.
Option B)
If the specialized operation are not part of the same sequence and must be called under certain "special" circumstances then let a specialized version of a client call those specialized operations. Warning, this is not so pure nor low coupling but when both objects ( the client and the service ) are created by the same "condition" or builder then most of the times is ok.
class Vehicle {
public void drive() {
....
}
}
class ConvertibleVehicle extends Vehicle {
// specialized version may override base operation or may not.
public void drive() {
...
}
public void foldRoof() { // specialized operation
...
}
}
Almost the same as the previous example, only in this case foldRoof is public also.
The difference is that I need an specialized client:
// Client ( base handler )
public class FleetHandler {
public void handle( Vehicle [] fleet ) {
for( Vehicle v : fleet ) {
v.drive();
}
}
}
// Specialized client ( sophisticate handler that is )
public class RoofAwareFleetHandler extends FleetHandler {
public void handle( Vehicle [] fleet ) {
for( Vehicle v : fleet ) {
// there are two options.
// either all vehicles are ConvertibleVehicles (risky) then
((ConvertibleVehicles)v).foldRoof();
v.drive();
// Or.. only some of them are ( safer ) .
if( v instenceOf ConvertibleVehicle ) {
((ConvertibleVehicles)v).foldRoof();
}
v.drive();
}
}
}
That instaceof look kind of ugly there, but it may be inlined by modern vm.
The point here is that only the specialized client knows and can invoke the specialized methods. That is, only RoofAwareFleetHandler can invoke foldRoof() on ** ConvertibleVehicle**
The final code doesn't change ...
public class Main {
public static void main( String [] args ) {
FleetHandler fleetHandler = .....
Vehicles [] fleet = ....
fleetHandler.handle( fleet );
}
}
Of course, I always make sure the fleethandler and the array of Vehicles are compatible ( probably using abstrac factory or builder )
I hope this helps.
This is a good question. What it implies is that you have (or expect to have) code that asks a Vehicle to (for instance) foldRoof(). And that's a problem, because most vehicles shouldn't fold their roofs. Only code that knows it's dealing with a ConvertibleVehicle should call that method, which means it is a method that should be only in the ConvertibleVehicle class. It's better this way; as soon as you try to call Vehicle.foldRoof(), your editor will tell you it can't be done. Which means you either need to arrange your code so that you know you're dealing with a ConvertibleVehicle, or cancel the foldRoof() call.
I think most people are missing the point of Delta's question. It looks to me like he/she isn't asking about what inheritance is. He/She is asking about subclasses implementing functionality that is not a natural fit for a base class, and the resulting mess that can ensue. I.e. the pushing of specific methods / functionality up the hierarchy chain, or requiring that subclasses implement a contract for functionality that isn't a natural fit.
There is also the matter of whether it is valuable to be able to treat a base class like the subclass in every case (to avoid casting and use them interchangeably). *edit -- this is called the Liskov substitution principle (thanks for reminding me, Kyle).
This is just what subclassing does: adds functionality not present in a base class.
class MyVehicle : public Vehicle {
public:
void MyNewFunction()
...
There are two (really just) different flavors of inheritance: public and private, reflecting the Is-A and Has-A relationships respectively. With public inheritance, you're directly adding stuff to a class. If I have class Animal with methods Eat() and Walk(), I may make a subclass called Cat which has the method Purr(). A Cat then has public methods Eat, Walk, and Purr.
In the case of a Stack based on a LinkedList however, I may say that a Stack HAS-A LinkedList internally. As such, I do not expose any features of the base class publically, I retain them as private and have to explicitly offer whatever I choose as public. A list may have a method Insert(), but for the Stack, I restrict the implementation and rexpose it as Push(). No previous public methods are exposed.
In C++, this is defined by the access modifier given before the base class. Above, I'm using public inheritance. Here, I use private inheritance:
class MyVehicle : private Engine {
This reflects that MyVehicle HAS-An Engine.
Ultimately, subclassing takes everything available in the base class and adds new stuff to it.
EDIT:
With this new information it seems that you're really looking for, it seems, is interfaces as stated by an earlier (voted down) comment. This is one of the big problems with inheritance - granularity. One of C++'s big complaints is its implementation of multiple inheritance (an option to accomplish this.) Can you state specifically what language you're using so we can advise properly?
To add on to Kyle W. Cartmell's excellent answer, and to perhaps simplify Oscar Reyes's answer a tad...
You might want to consider having the base class define a method called prepareToDrive() where inherited classes could put any setup tasks that need to be done before starting up. Calling drive() would be the way to start everything up from the user's perspective, so we would need to refactor drive into a "setup" phase and a "go" phase.
public class Vehicle {
protected void prepareToDrive() {
// no-op in the base class
}
protected abstract void go();
public final void drive() {
prepareToDrive();
go();
}
}
Now, subclasses must implement the protected method go() (really bad method name, but you get the idea), which is where they do their class-specific handling of driving.
Now, your inherited class could look like this:
public class ConvertableVehicle extends Vehicle {
// override setup method
protected void prepareToDrive() {
foldRoof();
}
protected void go() {
// however this works
}
protected void foldRoof() {
// ... whatever ...
}
}
This structure would also help when you run into class TractorTrailerRig that needs to make sure the trailer is loaded and correctly attached before it can drive.
How does the user of Vehicle know its a ConvertibleVehicle? Either they need to dynamic cast to ensure it is correct, or you've provided a method in Vehicle to get the objects real type.
In the first case the user already has a ConvertibleVehicle as part of dynamic cast. They can just use the new pointer/reference to access ConvertiblVehicle's methods
In the second case where the user verifies the objects type with one of Vehicles methods they can just cast the Vehicle to ConvertibleVehicle and use it.
Generally, casting is a bad idea. Try to do everything with the base class pointer. Your car example doesn't work well because the methods are too low level, build higher level virtual functions.
All that said. I have needed to all a derived classes methods from the base class. I could have cast to the derived class but it was involved in a framework and would have required much more effort. The old adage "all problems can be solved with one more layer of indirection" is how I solved this. I called a virtual method in the base class with the 'name' of the function I wanted to call. 'Name' can be a string or an integer depending on your needs. It's slower, but you should only need to do it rarely, if you class hierarchy is expressive enough.
Having ConvertibleVehicle subclass Vehicle and add its own methods as you describe is perfectly fine. That part of the design is OK. The trouble you have is with fleet. ConvertibleFleet should not be a subclass of VehicleFleet. An example will show you why. Let's say VehicleFleet is like this:
public class VehicleFleet {
// other stuff...
public void add(Vehicle vehicle) {
// adds to collection...
}
}
This is perfectly fine and sensible, you can add any Vehicle or subclass of it to a VehicleFleet. Now, let's say we also have another kind of vehicle:
public class TruckVehicle extends Vehicle {
// truck-specific methods...
}
We can also add this to a VehicleFleet since it's a vehicle. The problem is this: if ConvertibleFleet is a subclass of VehicleFleet, that means we can also add trucks to ConvertibleFleet. That's wrong. A ConvertibleFleet is not a proper subclass, since an operation that's valid for its parent (adding a truck) is not valid for the child.
The typical solution is to use a type parameter:
public class VehicleFleet<T extends Vehicle> {
void add(T vehicle) {
// add to collection...
}
}
This will let you define fleets specific to certain vehicle types. Note that this also means there is no "base" VehicleFleet class that you can pass to functions that don't care what kind of vehicle the fleet has. This can be remedied using another layer of base class (or interface):
public interface VehicleFleetBase {
Vehicle find(String name);
// note that 'add' methods or methods that pass in vehicles to the fleet
// should *not* be in here
}
public class VehicleFleet<T extends Vehicle> {
void add(T vehicle) {
// add to collection...
}
Vehicle find(String name) {
// look up vehicle...
}
}
For methods that are pulling vehicles out of fleets and don't care what kind they are, you can pass around VehicleFleetBase. Methods that need to insert vehicles use VehicleFleet<T> which is safely strongly-typed.