I am not an expert in OOPS and or design patterns.
I have come across this situation: Is a car with a bumper sticker subclass of a car?
If not then how can I add dynamic properties to instance of an object? For example a car, a car with bumper sticker etc.
Not all cars come with a bumper sticker. One can add a bumper sticker and even more than one bumper sticker. I can not implement a sticker with car, afaik, implementing me will force me to add stickers. A bumper sticker on a car is one new property that came into existence after car (object?) was created.
You can use the Decorator Design Pattern for cases like this. It will allow you to "add dynamic properties to instance of an object" which is what you mentioned, you can add any amout of stickers or any other property, in all combinations possible by "decorating" your car class.
The changes to Car you are talking about are dynamic attributes. Personally I would implement a collection of Accessories in the Car class, one of which would be a BumperSticker.
You can then add and remove Accessories without having to subclass Car for all the options available.
If you go down the inheritance route think about the situation when a car has a BumperSticker and Spoilers, you would have multiple inheritance which is frowned upon in C++ and not available in other languages.
If the bumper sticker is a common thing in your case, you can set a boolean attribute (true/false) or a string if that's it in your case.
If the bumper sticker is complicated to be a class of it self, perhaps the Car should Implement the sticker? (I am referring to Implementation in Java here)
As for Dynamic, would a database table of properties relating to the car be acceptable?
Don't overcomplicate this.
class Car
{
public:
bool hasBumperSticker() const { return m_hasBumperSticker; }
private:
bool m_hasBumperSticker;
};
Or, if the bumper sticker has its own properties:
class Car
{
public:
bool hasBumperSticker() const { return m_bumperSticker != 0; }
private:
BumperSticker* m_hasBumperSticker;
};
Actually, when you buy a car you choose the car itself and a set of options (music, interior, etc). As in a real life you can introduce 'options' in your car class. In a simple case it looks like (C++):
class Car {
enum CarOptions {
Bumper,
...
};
...
int options() const { return m_options; }
void setOptions(int options) { m_options = options }
...
};
Car c;
c.setOptions(c.options() | Car::Bumper);
Of course, this solution has it's own pros and cons, as any other.
Related
Why does object's type refer to its interface? Why the term type is used here? In terms of C++ I am not able to understand it.
Gamma, Erich. Design Patterns: Elements of Reusable Object-Oriented
Software (Addison-Wesley Professional Computing Series) (Kindle
Locations 593-596). Pearson Education. Kindle Edition.
An object’s class defines how the object is implemented. The class
defines the object’s internal state and the implementation of its
operations. In contrast, an object’s type only refers to its
interface—the set of requests to which it can respond. An object can
have many types, and objects of different classes can have the same
type.
An oversimplification...
Interface - a list of things that a class have and the things that it can do... a list of things that answer the "Whats"
Implementation - answers the question on "How" the "Whats" are accomplished.
Example:
An interface IPackageMover that does 2 things and 2 classes (types) that actually implements the interface (and also do other things aside from the interface requires)
// the interface
public interface IPackageMover
{
string GetName();
void public void MoveTo(Package package, string newAddress);
}
// the "type" that has the implementation
public class JoeThePackageMover : IPackageMover
{
public string GetName()
{
return "Joe";
}
public void MoveTo(Package package, string newAddress)
{
PickUp(package);
Drive(newAddress);
DropOff(package);
}
public void PickUp(Package package)
{
// do stuff
}
public void Drive(string newAddress)
{
// do stuff
}
public void DropOff(Package package)
{
// do stuff
}
}
// another "type" with the same interface
public class PassTheBuckPackageMover : IPackageMover
{
public string GetName()
{
return "What do you want it to be?";
}
public void MoveTo(Package package, string newAddress)
{
var joe = new JoeThePackageMover();
joe.MoveTo(package, newAddress);
}
public void Chill()
{
//do stuff
}
}
Why does object's type refer to its interface? Why the term type is used here? In terms of C++ I am not able to understand it.
Objects in OOP are not very different from the real world. For example :
A Car IS-A Vehicle. By this definition, a Car has the ability to transport people/cargo from one place to another.
A Car is also a Car. By this definition, it has the ability to be driven using a steering wheel.
In the above example, a Car IS-A Car and a Car is also a Vehicle because it can be driven using a steering wheel to move cargo/people from one place to another. In other words, the type of an object in the real world is defined by the things you can do with it (vis-à-vis it's interface.)
If we use the above analogy in programming, Car is a subclass of Vehicle and code that has a Car object can use all functions from Vehicle as well as Car. This would mean that a Car IS-A Vehicle and a Car. In conclusion, the type of object is defined by its interface, i.e the set of operations it supports.
Once my teacher asked me to give example of polymorphism from class room.
I told him that you are best example of polymorphism. As in college you are a teacher and in home you are husband or father. So your are one method but in different states you are behaving accordingly. And also you are extending human so you can be treated polymorphically as human.
(Considering in mind definition of polymorphism: Acquiring more than one form)
Can it be consider as good example of polymorphism ?
Thanks.
In your example, you give different behaviours for different states.
In OOP this is expressed through interfaces.
So, it would be modelled something like this:
class Human
{
Date Birthdate;
}
interface ITeacher
{
void Teach();
}
interface IHusband
{
void Pray();
}
interface IFather
{
void Love(); // methods in IFather and IHusband can be interchanged
}
class Person extends Human implements ITeacher, IHusband, IFather
{
// implementations inserted here
}
Now you can use those behaviours and the fact that he is a human in different cases.
Like:
Human yourTeacher = new Human("1970/05/01");
Class class = new Class();
class.Teachers.Add(yourTeacher); // expecting that it is a collection of ITeachers.
Pub pub = new Pub();
pub.DrunkPeople.Add(yourTeacher); // accepting only humans older than 21 here
So, polymorphism is about ONE object that behaves different in different cases... and inheritance.
While reading about abstraction, I came across the following statement
"Abstraction captures only those details about an object that are relevant to the current perspective"
For eg.
From the driver's perspective, Car class would be
public class Car
{
void start();
void applybrakes();
void changegear();
void stop();
}
From the mechanic's perspective, Car class would be
public class Car
{
void changeOil();
void adjustBrakes();
}
My question,
While designing a system, do we design for one user perspective(either driver or mechanic) or can
we design for multiple user perspective and further abstract out based on user type?
Hope my question is clear.
Thanks
Depending on your use case you might need to deign for multiple users. In your example, if your car will be used by both the mechanic and the driver, then you cannot just ignore one set of users. In that case, you can still abstract details by using Interfaces.
You could design your object like this:
interface IDrivable {
void start();
void applyBrakes();
void changeGear();
void stop();
}
interface IFixable {
void changeOil();
void adjustBrakes();
}
public class Car : IDrivable, IFixable {
// implement all the methods here
}
Now, when a mechanic wants the car, you don't give him a Car object, instead give him an IFixable object. Similarly, the driver gets an IDrivable object. This keeps the relevant abstraction for both sets of users simultaneously.
class Driver {
private IDrivable car;
public Driver(IDrivable car) {
this.car = car;
}
public driveCar() {
this.car.start();
this.car.accelerate();
//this is invalid because a driver should not be able to do this
this.car.changeOil();
}
}
Similary, a mechanic won't have access to the methods in the interface IDrivable.
You can read more about interfaces here. Even though this is the MSDN link and uses C#, all major languages support interfaces.
I think you may be inferring too much from "perspective." I wouldn't take perspective here to mean a person or user so much as a vantage point. The idea of a view here is maybe not even a good metaphor. What we're really talking about here is division of responsibility between the smaller objects that we use to compose the larger objects.
The whole point of this idea is decoupling and modularity. You want objects that you can pull out and replace without changing everything around them. So you want your objects to be coherent, for their methods and variables to be closely related.
You might be able to get some mileage from the user metaphor in terms of the interface-client relationship between objects.
I hear (and read on this site) a lot about "favour composition over inheritance".
But what is Compositon? I understand inheritance from the point of Person : Mammal : Animal, but I can't really see the definition of Compostion anywhere.. Can somebody fill me in?
Composition refers to combining simple types to make more complex ones. In your example, composition could be:
Animal:
Skin animalSkin
Organs animalOrgans
Mammal::Animal:
Hair/fur mammalFur
warm-blooded-based_cirulation_system heartAndStuff
Person::Mammal:
string firstName
string lastName
If you wanted to go totally composition (and get rid of all inheritance) it would look like this:
Animal:
Skin animalSkin
Organs animalOrgans
Mammal:
private Animal _animalRef
Hair/fur mammalFur
warm-blooded-based_cirulation_system heartAndStuff
Person:
private Mammal _mammalRef
string firstName
string lastName
The advantage to this approach is that the types Mammal and Person do not have to conform to the interface of their previous parent. This could be a good thing because sometimes a change to the superclass can have serious effects on the subclasses.
They still can have access to the properties and behaviours of these classes through their private instances of these classes, and if they want to expose these former-superclass behaviours, they can simply wrap them in a public method.
I found a good link with good examples here: http://www.artima.com/designtechniques/compoinh.html
Composition is simply the parts that make up the whole. A car has wheels, an engine, and seats. Inheritance is a "is a " relationship. Composition is a "has a" relationship.
There are three ways to give behavior to a class. You can write that behavior into the class; you can inherit from a class that has the desired behavior; or you can incorporate a class with the desired behavior into your class as a field, or member variable. The last two represent forms of code reuse, and the final one - composition - is generally preferred. It doesn't actually give your class the desired behavior - you still need to call the method on the field - but it puts fewer constraints on your class design and results in easier to test and easier to debug code. Inheritance has its place, but composition should be preferred.
class Engine
{
}
class Automobile
{
}
class Car extends Automobile // car "is a" automobile //inheritance here
{
Engine engine; // car "has a" engine //composition here
}
Composition - Functionality of an object is made up of an aggregate of different classes. In practice, this means holding a pointer to another class to which work is deferred.
Inheritance - Functionality of an object is made up of it's own functionality plus functionality from its parent classes.
As to why composition is preferred over inheritance, take a look at the Circle-ellipse problem.
An example of Composition is where you have an instance of a class within another class, instead of inheriting from it
This page has a good article explaining why people say "favour composition over inheritance" with some examples of why.
composition
simply mean using instance variables that are references to other objects.
For an illustration of how inheritance compares to composition in the code reuse department, consider this very simple example:
1- Code via inheritance
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {
System.out.println("Peeling is appealing.");
return 1;
}
}
class Apple extends Fruit {
}
class Example1 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
When you run the Example1 application, it will print out "Peeling is appealing.", because Apple inherits (reuses) Fruit's implementation of peel(). If at some point in the future, however, you wish to change the return value of peel() to type Peel, you will break the code for Example1. Your change to Fruit breaks Example1's code even though Example1 uses Apple directly and never explicitly mentions Fruit.
for more info ref
Here's what that would look like:
class Peel {
private int peelCount;
public Peel(int peelCount) {
this.peelCount = peelCount;
}
public int getPeelCount() {
return peelCount;
}
//...
}
class Fruit {
// Return a Peel object that
// results from the peeling activity.
public Peel peel() {
System.out.println("Peeling is appealing.");
return new Peel(1);
}
}
// Apple still compiles and works fine
class Apple extends Fruit {
}
// This old implementation of Example1
// is broken and won't compile.
class Example1 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
2- Code via composition
Composition provides an alternative way for Apple to reuse Fruit's implementation of peel(). Instead of extending Fruit, Apple can hold a reference to a Fruit instance and define its own peel() method that simply invokes peel() on the Fruit. Here's the code:
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {
System.out.println("Peeling is appealing.");
return 1;
}
}
class Apple {
private Fruit fruit = new Fruit();
public int peel() {
return fruit.peel();
}
}
class Example2 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
for more information ref
What is good design in this simple case:
Let's say I have a base class Car with a method FillTank(Fuel fuel) where
fuel is also a base class which have several leaf classes, diesel, ethanol etc.
On my leaf car class DieselCar.FillTank(Fuel fuel) only a certain type of fuel
is allowed (no surprises there:)). Now here is my concern, according to my interface every car can be tanked with any fuel, but that seems wrong to me, in every FillTank() implementation check the input fuel for the correct type and if not throw error or something.
How can I redesign such case to a more accurate one, is it even possible?
How to design a base method which takes a base-class for input without getting these "strange results"?
Use a generic base class (if your language supports it (the below is C#)):
public abstract class Car<TFuel> where TFuel : Fuel
{
public abstract void FillTank(TFuel fuel);
}
Basically this enforces any class that inherits from car to specify which type of fuel it uses. Furthermore, the Car class imposes a restriction that TFuel must be some subtype of the abstract Fuel class.
Lets say we have some class Diesel which is simple:
public class Diesel : Fuel
{
...
}
And a car which only runs on diesel:
public DieselCar : Car<Diesel>
{
public override void FillTank(Diesel fuel)
{
//perform diesel fuel logic here.
}
}
Object-oriented programming alone cannot handle this problem well. What you need is generic programming (C++ solution shown here):
template <class FuelType>
class Car
{
public:
void FillTank(FuelType fuel);
};
Your diesel car is then just a specific car, Car<Diesel>.
If there is a hard boundary between types of cars and types of fuel, then FillTank() has no business being in the base Car class, since knowing that you have a car doesn't tell you what kind of fuel. So, for this to ensure correctness at compile time, FillTank() should be defined in the subclasses, and should only take the Fuel subclass that works.
But what if you have common code that you don't want to repeat between the subclasses? Then you write a protected FillingTank() method for the base class that the subclass's function calls. Same thing goes for Fuel.
But what if you have some magic car that runs on multiple fuels, say diesel or gas? Then that car becomes a subclass of both DieselCar and GasCar and you need to make sure that Car is declared as a virtual superclass so you don't have two Car instances in a DualFuelCar object. Filling the tank should Just Work with little or no modification: by default, you'll get both DualFuelCar.FillTank(GasFuel) and DualFuelCar.FillTank(DieselFuel), giving you an overloaded-by-type function.
But what if you don't want the subclass to have a FillTank() function? Then you need to switch to run time checking and do what you thought you had to: make the subclass check Fuel.type and either throw an exception or return an error code (prefer the latter) if there is a mismatch. In C++, RTTI and dynamic_cast<> are what I would recommend. In Python, isinstance().
a double dispatch can be used for this: accept some fuel before before filling. Mind you that in language that don't support it directly, you introduce dependencies
It sounds like you just want to restrict the type of fuel that goes into your diesel car. Something like:
public class Fuel
{
public Fuel()
{
}
}
public class Diesel: Fuel
{
}
public class Car<T> where T: Fuel
{
public Car()
{
}
public void FillTank(T fuel)
{
}
}
public class DieselCar: Car<Diesel>
{
}
Would do the trick e.g.
var car = new DieselCar();
car.FillTank(/* would expect Diesel fuel only */);
Essentially what you are doing here is allowing a Car to have specific fuel types. It also allows you to create a car that would support any type of Fuel (the chance would be a fine thing!). However, in your case, the DieselCar, you would just derive a class from car and restrict it to using Diesel fuel only.
use the is operator to check against the accepted classes, and you can throw an exception in the constructor
I think the accepted method would be to have a ValidFuel(Fuel f) method in your base class that throws some sort of NotImplementedException (different languages have different terms) if the "leaf" cars don't override it.
FillTank could be then be entirely in the base class and call ValidFuel to see if it's valid.
public class BaseCar {
public bool ValidFuel(Fuel f) {
throw new Exception("IMPLEMENT THIS FUNCTION!!!");
}
public void FillTank(Fuel fuel) {
if (!this.ValidFuel(fuel))
throw new Exception("Fuel type is not valid for this car.");
// do what you'd do to fill the car
}
}
public class DieselCar:BaseCar {
public bool ValidFuel(Fuel f) {
return f is DeiselFuel
}
}
In a CLOS-like system, you could do something like this:
(defclass vehicle () ())
(defclass fuel () ())
(defgeneric fill-tank (vehicle fuel))
(defmethod fill-tank ((v vehicle) (f fuel)) (format nil "Dude, you can't put that kind of fuel in this car"))
(defclass diesel-truck (vehicle) ())
(defclass normal-truck (vehicle) ())
(defclass diesel (fuel) ())
(defmethod fill-tank ((v diesel-truck) (f diesel)) (format nil "Glug glug"))
giving you this behaviour:
CL> (fill-tank (make-instance 'normal-truck) (make-instance 'diesel))
"Dude, you can't put that kind of fuel in this car"
CL> (fill-tank (make-instance 'diesel-truck) (make-instance 'diesel))
"Glug glug"
Which, really, is Common Lisp's version of double dispatch, as mentioned by stefaanv.
you can extend your original Car interface
interface Car {
drive();
}
interface DieselCar extends Car {
fillTank(Diesel fuel);
}
interface SolarCar extends Car {
chargeBattery(Sun fuel);
}
}