This question already has answers here:
Abstraction VS Information Hiding VS Encapsulation
(22 answers)
Difference between abstraction and encapsulation?
(40 answers)
Closed 2 months ago.
What exactly is the difference between encapsulation and abstraction in Java? Any brief examples would also be appreciated.
Abstraction and encapsulation are two great flavors that taste great together.
Encapsulation is minimizing what you expose to the user of your code. That "user" may be the rest of your code, or whoever uses the code you publish.
There some definite benefits to encapsulation:
The user of your code doesn't depend on parts of your program that are likely to change. When you change your program, they don't have to change their code
You are more in control of exactly how your code and state changes over the lifetime of your program. You must handle fewer scenarios, and will have fewer unexpected problems to fix
I don't know Java, but here is a small example of encapsulation in C#:
public class Giraffe
{
public Giraffe(int heightInFeet)
{
this.heightInFeet = heightInFeet;
this.numberOfSpots = heightInFeet * 72;
}
public override string ToString()
{
return "Height: " + heightInFeet + " feet"
+ " Number of Spots: " + numberOfSpots;
}
private int heightInFeet;
private int numberOfSpots;
}
Instead of exposing numberOfSpots, it is encapsulated within the class, and exposed via the ToString method.
Abstraction is using extension points to let the choice be deferred to a different part of which exact code is run. That choice could be made elsewhere in your program, in another program, or dynamically at runtime.
There are also strong benefits to abstraction:
When you change your code that implements an abstraction, the user of the abstraction doesn't have to change their code. As long as the abstraction doesn't change, the users won't have to change their code.
When you write code that uses an abstraction, you can write code once that will be reusable against any new code that implements that abstraction. You can write less code to do more.
A highly used abstraction in C# is IEnumerable. Lists, Arrays, Dictionaries, and any other type of collection class all implement IEnumerable. The foreach loop structure and the entirety of the LINQ library are based on that abstraction:
public IEnumerable<int> GetSomeCollection()
{
// This could return any type of int collection. Here it returns an array
return new int[] { 5, 12, 7, 14, 2, 3, 7, 99 };
}
IEnumerable<int> someCollectionOfInts = GetSomeCollection();
IEnumerable<string> itemsLessThanFive = from i in someCollectionOfInts
where i < 5
select i.ToString();
foreach(string item in itemsLessThanFive)
{
Console.WriteLine(item);
}
You can easily write your own abstractions, too:
public interface IAnimal
{
bool IsHealthy { get; }
void Eat(IAnimal otherAnimal);
}
public class Lion : IAnimal
{
public Lion()
{
this.isHealthy = true;
}
public bool IsHealthy
{
get { return isHealthy; }
}
void Eat(IAnimal otherAnimal)
{
if(otherAnimal.IsHealthy && !(otherAnimal is SlimeMold))
{
isHealthy = true;
}
else
{
isHealthy = false;
}
}
private bool isHealthy;
}
IAnimal someAnimal = PullAnAnimalOutOfAWoodenCrate();
Console.WriteLine("The animal is healthy?: " + someAnimal.IsHealthy);
You can use both together, as I did with IAnimal, and IsHealthy. IAnimal is an abtraction, and having only a get accessor, and no set accessor on IsHealthy is encapsulation.
These two concepts are quite different.
Abstraction is the practice of making a base class 'abstract' and then extending its functionality. An abstract class is something that doesn't exist in a concrete matter; its only purpose is to be extended. Think of if you were writing classes to represent different species. All of your different species might extend an abstract Animal class because they would all share common attributes as animals. However, you would never instantiate an Animal object, because every animal you see in the world is a squirrel, or a dog, or a fish ... or some kind of concrete implementation of that base, abstract animal class.
Encapsulation is the practice of making your class variables private, and then allowing access to them from get and set methods. The purpose of this is separate the way your data is accessed and the way it is implemented. For example, if you have some variable that has a requirement, that every time it is changed, it also increments a second variable by 1, then you would encapsulate that functionality; that way your code is more reliable because you don't have to remember to adhere that rule every time you'd access the original variable.
If you want specific code examples, I'd recommend just doing a google search, because there's a lot of examples like that available. Here's two:
http://www.tutorialspoint.com/java/java_abstraction.htm
http://www.tutorialspoint.com/java/java_encapsulation.htm
Encapsulation is to protect your member variables or methods from the outside world.
Abstraction is the way to have specific implementation. that is which implementation to use is unknown to the user.
Encapsulation is part of abstraction. The notion of abstraction is one of creating an object to represent another object. Typically, the original object is more complex than the abstraction. An abstraction is thus a representation, usually as an aid to memory, for terminology/communication etc. Think of it like this: abstract art is a representation of something else. A steering wheel, gearshift and 2/3 pedals is an abstraction of how a car works.
Basically, the abstraction allows you to represent something complex, with a lot of details, as something a lot simpler. In my opinion, this is related to 'chunking' in cognitive science. We're not able to keep complex things in our head, so we simplify by abstracting, then using the abstraction. Design Patterns are another great example. Instead of talking about details, we can talk about Command, State or Strategy pattern etc.
Encapsulation is part of forming/creating an abstraction. The smaller an object's interface, the easier it is to abstract. You don't need to know how an engine and gearbox work to drive a car, you just need to understand their abstractions (gear shift and accelerator). The details of the engine and gearbox are encapsulated (into the interface) in order to create the abstraction.
Encapsulation is needed for abstraction because an abstaction can't deal with all the real details and complexity (otherwise its not an abstraction). So the gearshift is an incomplete representation (or model) of a gearbox, but its complete enough for everyday use. Encapsulation can be thought of as 'hiding details', which is necessary for creating a simpler representation.
Its also important to discuss the concept of an 'interface'. For the most part, the terms 'interface' and 'abstraction' are more less interchangeable in this instance. An interface is the part of a system with which the user deals or interacts. The interface to a car is the steering wheel, gear shift and pedals etc. The abstraction produces an interface. You don't deal with the engine/gearbox directly, you deal with their respective interfaces.
Another reason for encapsulation is because we're dealing with an incomplete model/abstraction, we don't understand the full complexity of the original, and can't be trusted to deal with all the variables (because we don't understand the full model). This is important for decoupling, because without abstraction, interacting components would know too much about each other. Think about it, because every car has a steering wheel, pedals and gearshift, you can drive any car, regardless of engine type etc. Also, the gearbox is abstracted from the engine. Otherwise each custom engine would need a custom gearbox.
Similarly, a Class is an abstraction. The class represents some complex model, through its interface - the public members of the class. This interface is created through encapsulation. The class presents a simplified interface of its more complex implementation to its collaborators. You can also think of it as a 'need to know' situation. The collaborators of the class don't need to know exactly how it works. Just as you don't need to know how an engine works to drive a car.
Encapsulation, interfaces and abstraction play a critical role in cohesion and coupling, and therefore maintenance of your code. If you don't create good abstractions, and violate the 'need to know' principle, then your code becomes entangled, fragile and a nightmare to change, because there is no 'buffering'. The OO concept of 'tell don't ask' is also related to this.
Related
This question already has answers here:
Object-oriented design: Saving complex objects
(2 answers)
Closed 5 years ago.
We have a business model that requires, say, different types of vehicles to be identified. For example, motorcycle, boat, yacht, farm equipment, snowmobiles, heavy truck, light truck, passenger car, and "Other".
I think there are two ways to handle it: Create a Vehicle class with a few subclasses, say, boat, truck, car and have a single enum indicating the actual type. This would work, allowing you to represent vehicles that share some common features with common subclasses. But it allows you to have mismatched enums with the classes.
I think the traditional way to handle it is to have a separate subclass for each type, which may subclass the vehicle, or a subclass of vehicle. For example, heavy and light truck might subclass truck; boat and yacht might subclass boat; snowmobile might subclass vehicle. The problem is, it doesn't really lend itself to representing the concept of other.
Does anyone have any patterns or best-practices for these sorts of scenarios?
Peter
EDIT:
The purpose of the object is to convey information about the vehicle and to be able to display that information in a user-friendly way. For example, pull the data from a database and display it on a screen to be viewed/edited.
This leads to another downside to the traditional OO means that leans away from type indicators for actual types, in that to display the type one would need to perform some sort of instance-of and convert the value to something user-friendly.
(Also, clarified I was talking about a single enum, not an enum per subclass.)
I would start with a Vehicle and not add too much abstraction.
I wouldn't use the class hierarchy to describe something you could use a field to describe.
Is the code for these types so different?
For example, say you have a type you didn't think of before. like an aqua-car (which is a car which can travel over water) or a seyway, or a unicycle. You could create a new class for each type or you could have it entirely data driven with fields like
name: aqua-car
type: Exotic Car
travelsOnWater: true
travelsOdLand: true
wheels: 4
I suggest you read You Ain't Gonna Need It Better to add only the abstraction you need, not the abstraction you can imagine.
The Real Question
How different do two "things" need to be before they deserve their own class?
The Answer
It depends entirely on how you are going to use the objects.
Will you be comparing them based on some property they have (e.g., does it float?)? If so, a single class with a differentiating property makes sense.
Are you going to display your objects on an interface? Would it make sense within your application to display Light Trucks and Heavy Trucks in a single table? If they cannot meaningfully exist and be displayed as one data set, then it makes sense to have two classes.
Those are just two examples. The point is, if you create a new class, it should be useful. Java is particularly prone to over-abstraction.
What do I do about Other?
Other sounds like a group of Vehicles that are not Trucks and not Cars. It sounds like you want to catch all other Vehicles and put them in one class. Why not use the Vehicle class? Don't create another class that derives from Vehicle but adds zero functionality. The same usefulness test applies here.
Is a Vehicle useful enough to satisfy my needs for all "other" vehicles? If not, I need to create more classes.
I took your advice and created two useful classes. Now, I can't tell them apart and I refuse to use instanceof. What do I do?
No matter how abstracted your classes are, I will always be able to add instances your class to a List<Object> and will then be unable to tell them apart. You cannot bulletproof your design.
Let me put it another way - if you add Eggs and Cars to a List, and you later need to differentiate between Eggs and Cars, then there is a problem with your List, not the Eggs and Cars.
There is not simple answer for your question. Because its depend on the business logic you will have to perform with that data structure.
I would start with an interface Vehicle that will resolve a Identyficator from to get the description of concrete representant.
interface VehicleIdentyficator {
String identyficator();
}
interface Vehicle {
Identyficator getIdentyficator();
}
With this you are not limited to class, enum or other kind of design.
Then i would use class hierarchy to describe the properties of each vehicle.
After that add some logic/behavioural aspects to the code and get a look that my data structures are valid for the task.
At the end of the day the important aspect is to perform some operations.
For example there is no point of creation three classes Truck, LightTruck and HavyTruck.
You could create a class that describe them by task they perform
They can transport on ground
The Light truck can carry less load but it used to travel in small cities.
The Heavy truck is opposite to Light. Have big Range carry more load.
When we compare to this a boat we see that boat is more like light truck the only difference is that it travel on water.
So try to understand the object not be what it is but what it can do. What tasks can be performed by it and what are the limitation. Then with your design will be really close to what you need.
I hope this sentence is correct and i will repeat myself. It seams that you are using those vehicles, not constructing them. So focus on their mission to full fill not on their physical aspects.
But you can do something like this
enum VechicleType implements VehicleIdentyficator {
TRUCK("TRUCK"),
HEAVY_TRUCK("HEAVY_TRUCK")
private final String indentyficator;
private VechicleType(String indetyficator) {
this.indentyficator = identyficator;
}
public String identyficator() {
return indentyficator;
}
}
But then every time you add some new vehicle you must cover all points where such new hard coded type will be used.
As others stated, I think it depends on how you're gonna use your vehicles.
If you just need to distinguish between types at some points, but you mostly handle all vehicles the same way, go for the enum type.
If you really need to specify different behaviors and you make use of shared features/behaviors, go for a full class hierarchy. That's also my preferred approach, because I feel like it offers more evolutivity.
The best way to handle type indicators in OO development is to not have type indicators.
Type indicators are a structured programming
(that think that predates object oriented programming) concept.
In OO, type is identified by type, not by an artificial indicator.
Edit:
If you have a fixed domain of things that you must represent with an object (for example: tractor, speed boat, row boat, motorcycle, mazda 626, pickup truck, deuce-and-a-half truck) then you can (perhaps should) represent each thing with a concrete class. The interesting design question will be based on what you need to do with the objects.
If you just need to know "is this a water vehicle" or "how many wheels does this have" then use an Interface with isWaterVehicle(), getWheelCount(), isTruck() methods. Implement the interface on your objects and hard code the answer. For example:
class SpeedBoat implements VehicleInfo
{
public int getWheelCount()
{
return 0;
}
public boolean isTruck()
{
return false;
}
public boolean isWaterVehicle()
{
return true;
}
}
If you have a large number of similar objects, use an abstract class to set the defaults.
abstract class AbstractTruck implements VehicleInfo
{
public final int isTruck()
{
return true;
}
}
Having come across the concept of immutable objects recently, I would like to know the best practices for controlling access to the state. Even though the object oriented part of my brain makes me want to cower in fear at the sight of public members, I see no technical issues with something like this:
public class Foo {
public final int x;
public final int y;
public Foo( int x, int y) {
this.x = x;
this.y = y;
}
}
I would feel more comfortable declaring the fields as private and providing getter methods for each but this seems overly complex when the state is explicitly read only.
What is the best practice for providing access to the state of an immutable object?
It depends entirely on how you're going to use the object. Public fields aren't inherently evil, it's just bad to default everything to being public. For example the java.awt.Point class makes its x and y fields public, and they aren't even final. Your example seems like a fine use of public fields, but then again you might not want to expose all of the internal fields of another immutable object. There is no catch-all rule.
I have thought the same in the past but usually end up making variables private and using getters and setters so that later on I'll still have the option of making changes to the implementation while keeping the same interface.
This did remind me of something I read recently in "Clean Code" by Robert C. Martin. In chapter 6 he gives a slightly different perspective. For example, on page 95 he states
"Objects hide their data behind abstractions and expose functions that operate on that data. Data structure expose their data and have no meaningful functions."
And on page 100:
The quasi-encapsulation of beans seems to make some OO purists feel better but usually provides no other benefit.
Based on the code sample, the Foo class would seem to be a data structure. So based on what I understood from the discussion in Clean Code (which is more than just the two quotes I gave), the purpose of the class is to expose data, not functionality, and having getters and setters probably does not do much good.
Again, in my experience, I have usually gone ahead and used the "bean" approach of private data with getters and setters. But then again, no one ever asked me to write a book about how to write better code so maybe Martin has something to say.
If your object is of local-enough usage that you don't care about the issues of breaking API changes for it in the future, there is no need to tack getters on top of the instance variables. But this is a general subject, not specific to immutable objects.
The advantage of using getters comes from one extra layer of indirection, which may come in handy if you are designing an object which will be widely used, and whose utility will extend into unforseeable future.
Regardless of immutability, you're still exposing the implementation of this class. At some stage you'll want to change the implementation (or perhaps produce various derivations e.g. using the Point example, you may want a similar Point class using polar coordinates), and your client code is exposed to this.
The above pattern may well be useful, but I'd generally restrict it to very localised instances (e.g. passing tuples of information around - I tend to find that objects of seemingly unrelated info, however, either are bad encapsulations, or that the info is related, and my tuple transforms into a fully-fledged object)
The big thing to keep in mind is that function calls provide a universal interface. Any object can interact with other objects using function calls. All you have to do is define the right signatures, and away you go. The only catch is that you have to interact solely through these function calls, which often works well but can be clunky in some cases.
The main reason to expose state variables directly would be to be able to use primitive operators directly on these fields. When done well, this can enhance readability and convenience: for example, adding Complex numbers with +, or accessing a keyed collection with []. The benefits of this can be surprising, provided that your use of the syntax follows traditional conventions.
The catch is that operators are not a universal interface. Only a very specific set of built-in types can use them, these can only be used in the ways that the language expects, and you cannot define any new ones. And so, once you've defined your public interface using primitives, you've locked yourself into using that primitive, and only that primitive (and other things that can be easily cast to it). To use anything else, you have to dance around that primitive every time you interact with it, and that kills you from a DRY perspective: things can get very fragile very quickly.
Some languages make operators into a universal interface, but Java doesn't. This is not an indictment of Java: its designers chose deliberately not to include operator overloading, and they had good reasons to do so. Even when you're working with objects that seem to fit well with the traditional meanings of operators, making them work in a way that actually makes sense can be surprisingly nuanced, and if you don't absolutely nail it, you're going to pay for that later. It is often much easier to make a function-based interface readable and usable than to go through that process, and you often even wind up with a better result than if you'd used operators.
There were tradeoffs involved in that decision, however. There are times when an operator-based interface really does work better than a function-based one, but without operator overloading, that option just isn't available. Trying to shoehorn operators in anyway will lock you into some design decisions that you probably don't really want to be set in stone. The Java designers thought that this tradeoff was worthwhile, and they might even have been correct about that. But decisions like this don't come without some fallout, and this kind of situation is where the fallout hits.
In short, the problem isn't exposing your implementation, per se. The problem is locking yourself into that implementation.
Actually, it breaks encapsulation to expose any property of an object in any way -- every property is an implementation detail. Just because everybody does this doesn't make it right. Using accessors and mutators (getters and setters) doesn't make it any better. Rather, the CQRS patterns should be used to maintain encapsulation.
I know only one prop to have getters for final properties. It is the case when you'd like to have access to the properties over an interface.
public interface Point {
int getX();
int getY();
}
public class Foo implements Point {...}
public class Foo2 implements Point {...}
Otherwise the public final fields are OK.
The class that you have developed, should be fine in its current incarnation. The issues usually come in play when somebody tries to change this class or inherit from it.
For example, after seeing above code, somebody thinks of adding another member variable instance of class Bar.
public class Foo {
public final int x;
public final int y;
public final Bar z;
public Foo( int x, int y, Bar z) {
this.x = x;
this.y = y;
}
}
public class Bar {
public int age; //Oops this is not final, may be a mistake but still
public Bar(int age) {
this.age = age;
}
}
In above code, the instance of Bar cannot be changed but externally, anybody can update the value of Bar.age.
The best practice is to mark all fields as private, have getters for the fields. If you are returning an object or collection, make sure to return unmodifiable version.
Immunatability is essential for concurrent programming.
An object with public final fields that get loaded from public constructor parameters effectively portrays itself as being a simple data holder. While such data holders aren't particularly "OOP-ish", they are useful for allowing a single field, variable, parameter, or return value to encapsulate multiple values. If the purpose of a type is to serve as a simple means of gluing a few values together, such a data holder is often the best representation in a framework without real value types.
Consider the question of what you would like to have happen if some method Foo wants to give a caller a Point3d which encapsulates "X=5, Y=23, Z=57", and it happens to have a reference to a Point3d where X=5, Y=23, and Z=57. If the thing Foo has is known to be a simple immutable data holder, then Foo should simply give the caller a reference to it. If, however, it might be something else (e.g. it might contain additional information beyond X, Y, and Z), then Foo should create a new simple data holder containing "X=5, Y=23, Z=57" and give the caller a reference to that.
Having Point3d be sealed and expose its contents as public final fields will imply that methods like Foo may assume it's a simple immutable data holder and may safely share references to instances of it. If code exists that make such assumptions, it may be difficult or impossible to change Point3d to be anything other than a simple immutable data holder without breaking such code. On the other hand, code which assumes Point3d is a simple immutable data holder can be much simpler and more efficient than code which has to deal with the possibility of it being something else.
You see this style a lot in Scala, but there is a crucial difference between these languages: Scala follows the Uniform Access Principle, but Java doesn't. That means your design is fine as long as your class doesn't change, but it can break in several ways when you need to adapt your functionality:
you need to extract an interface or super class (e.g. your class represents complex numbers, and you want to have a sibling class with polar coordinate representation, too)
you need to inherit from your class, and information becomes redundant (e.g. x can be calculated from additional data of the sub-class)
you need to test for constraints (e.g. x must be non-negative for some reason)
Also note that you can't use this style for mutable members (like the infamous java.util.Date). Only with getters you have a chance to make a defensive copy, or to change representation (e.g. storing the Date information as long)
I use a lot constructions very similar to the one you put in the question, sometimes there are things that can be better modeled with a (sometimes inmutable) data-strcuture than with a class.
All depends, if you are modeling an object, an object its defined by its behaviors, in this case never expose internal properties. Other times you are modeling a data-structure, and java has no special construct for data-structures, its fine to use a class and make public all the properties, and if you want immutability final and public off course.
For example, robert martin has one chapter about this in the great book Clean Code, a must read in my opinion.
In cases where the only purpose is to couple two values to each other under a meaningful name, you may even consider to skip defining any constructors and keep the elements changeable:
public class Sculpture {
public int weight = 0;
public int price = 0;
}
This has the advantage, to minimize the risk to confuse the parameter order when instantiating the class. The restricted changeability, if needed, can be achieved by taking the whole container under private control.
Just want to reflect reflection:
Foo foo = new Foo(0, 1); // x=0, y=1
Field fieldX = Foo.class.getField("x");
fieldX.setAccessible(true);
fieldX.set(foo, 5);
System.out.println(foo.x); // 5!
So, is Foo still immutable? :)
I have been told at some stage at university (and have subsequently read in upteen places) that using instanceof should only be used as a 'last resort'. With this in mind, is anyone able to tell be if the following code I have is a last resort. I have had a look around on stack overflow but cannot quite find a similar scenario - perhaps I have missed it?
private void allocateUITweenManager() {
for(GameObject go:mGameObjects){
if (go instanceof GameGroup) ((GameGroup) go).setUITweenManager(mUITweenManager);
}
}
where
mGameObjects is an array, only some of which are GameGroup type
GameGroup is a subclass of abstract class GameObject.
GameGroup uses interface UITweenable which has method setUITweenManager()
GameObject does not use interface UITweenable
I suppose I could equally (and probably should) replace GameGroup in my code above with UITweenable - I would be asking the same question.
Is there another way of doing this that avoids the instanceof? This code cannot fail, as such (I think, right?), but given the bad press instanceof seems to get, have I committed some cardinal sin of OOP somewhere along the line that has me using instanceof here?
Thanks in advance!
I learned about Visitor pattern in Compiler class at university, I think it might apply in your scenario. Consider code below:
public class GameObjectVisitor {
public boolean visit(GameObject1 obj1) { return true; }
.
.
// one method for each game object
public boolean visit(GameGroup obj1) { return true; }
}
And then you can put a method in GameObject interface like this:
public interface GameObject {
.
.
public boolean visit(GameObjectVisitor visitor);
}
And then each GameObject implements this method:
public class GameGroup implements GameObject {
.
.
.
public boolean visit(GameObjectVisitor visitor) {
visitor.visit(this);
}
}
This is specially useful when you've complex inheritance hierarchy of GameObject. For your case your method will look like this:
private void allocateUITweenManager() {
GameObjectVisitor gameGroupVisitor = new GameObjectVisitor() {
public boolean visit(GameGroup obj1) {
obj1.setUITweenManager(mUITweenManager);
}
};
for(GameObject go:mGameObjects){
go.visit(gameGroupVisitor);
}
}
EDIT
There are two primary things you can do here to relieve yourself of this specific instance of instanceof. (pun?)
Do as my initial answer suggested and move the method you are targeting up to the class you are iterating. This isn't ideal in this case, because the method doesn't make sense to the parent object, and would be polluting as Ted has put it.
Shrink the scope of the objects you are iterating to just the objects that are familiar with the target method. I think this is the more ideal approach, but may not be workable in the current form of your code.
Personally, I avoid instanceof like the plague, because it makes me feel like I completely missed something, but there are times where it is necessary. If your code is laid out this way, and you have no way to shrink the scope of the objects you are iterating, then instanceof will probably work just fine. But this looks like a good opportunity to see how polymorphism can make your code easier to read and maintain in the future.
I am leaving the original answer below to maintain the integrity of the comments.
/EDIT
Personally, I don't think this is a good reason to use instanceof. It seems to me that you could utilize some polymorphism to accomplish your goal.
Have you considered making setUITweenManager(...) a method of GameObject? Does it make sense to do this?
If it does make sense, you could have your default implementation do nothing, and have your GameGroup override the method to do what you want it to do. At this point, your code could just look like this then:
private void allocateUITweenManager() {
for(GameObject go:mGameObjects){
go.setUITweenManager(mUITweenManager);
}
}
This is polymorphism in action, but I am not sure it would be the best approach for your current situation. It would make more sense to iterate the Collection of UITweenable objects instead if possible.
The reason why instanceof is discouraged is because in OOP we should not examine object's types from outside. Instead, the idiomatic way is to let object themselves act using overriden methods. In your case, one possible solution could be to define boolean setUITweenManager(...) on GameObject and let it return true if setting the manager was possible for a particular object. However if this pattern occurs in many places, the top-level classes can get quite polluted. Therefore sometimes instanceof is "lesser evil".
The problem with this OPP approach is that each object must "know" all its possible use cases. If you need a new feature that works on your class hierarchy, you have to add it to the classes themselves, you can't have it somewhere separate, like in a different module. This can be solved in a general way using the visitor pattern, as others suggested. The visitor pattern describes the most general way to examine objects, and becomes even more useful when combined with polymorphism.
Note that other languages (in particular functional languages) use a different principle. Instead of letting objects "know" how they perform every possible action, they declare data types that have no methods on their own. Instead, code that uses them examines how they were constructed using pattern matching on algebraic data types. As far as I know, the closest language to Java that has pattern matching is Scala. There is an interesting paper about how Scala implements pattern matching, which compares several possible approaches: Matching Objects With Patterns. Burak Emir, Martin Odersky, and John Williams.
Data in object-oriented programming is organized in a hierarchy of classes. The problem of object-oriented pattern matching is how to explore this hierarchy from the outside. This usually involves classifying objects by their run-time type, accessing their members, or determining some other characteristic of a group of objects. In this paper we compare six different pattern matching techniques: object-oriented decomposition, visitors, type-tests/typecasts, typecase, case classes, and extractors. The techniques are compared on nine criteria related to conciseness, maintainability and performance. The paper introduces case classes and extractors as two new pattern-matching methods and shows that their combination works well for all of the established criteria.
In summary: In OOP you can easily modify data types (like add subclasses), but adding new functions (methods) requires making changes to many classes. With ADT it's easy to add new functions, but modifying data types requires modifying many functions.
The problem with instanceof is that you can suffer from future object hierarchy changes. The better approach is to use Strategy Pattern for the cases where you are likely to use instanceof. Making a solution with instanceof you are falling into a problem Strategy is trying to solve: to many ifs. Some guys have founded a community. Anti-IF Campaign could be a joke but untipattern is serious. In a long term projects maintaining 10-20 levels of if-else-if could be a pain. In your case you'd better make a common interface for all objects of your array and implement setUITweenManager for all of them through an interface.
interface TweenManagerAware{
setUITweenManager(UITweenManager manager);
}
It is always a bit "fishy" to me to mix objects of different classes in the same Collection. Would it be possible / make sense to split the single Collection of GameObjects into multiple Collections, one of mere GameObjects, another of UITweenables? (e.g. use a MultiMap keyed by a Class). Then you could go something like:
for (UITweenable uit : myMap.get(UITweenable.class)) {
uit.setUITweenManager(mUITweenManager);
}
Now, you still need an instanceof when you insert into the map, but it's better encapsulated - hidden from the client code who doesn't need to know those details
p.s. I'm not a fanatic about all the SW "rules", but Google "Liskov Substitution Principle".
You could declare setUITweenManager in GameObject with an implementation that does nothing.
You could create an method that returns an iterator for all UITweenable instances in array of GameObject instances.
And there are other approaches that effectively hide the dispatching within some abstraction; e.g. the Visitor or Adapter patterns.
... have I committed some cardinal sin of OOP somewhere along the line that has me using instanceof here?
Not really (IMO).
The worst problem with instanceof is when you start using it to test for implementation classes. And the reason that is particularly bad is that it makes it hard to add extra classes, etcetera. Here the instanceof UITweenable stuff doesn't seem to introduce that problem, because UITweenable seems to be more fundamental to the design.
When you make these sorts of judgement, it is best to understand the reasons why the (supposedly) bad construct or usage is claimed to be bad. Then you look at you specific use-case and make up whether these reasons apply, and whether the alternatively you are looking at is really better in your use-case.
You could use the mGameObjects container for when you need to do something on all game objects and keep a separate container only for GameGroup objects.
This will use some more memory, and when you add/remove objects you have to update both containers, but it shouldn't be a noticeable overhead, and it lets you loop very efficiently through all the objects.
The problem with this approach is that it doesn't usually appear at one place only in your code and thus makes it more or less painful to add another implementations of the interface in the future. Whether to avoid it depends on your consideration. Sometimes YAGNI can be applied an this is the most straightforward way.
Alternatives had been suggested by others, for example the Visitor pattern.
I have another suggestion of a way to avoid instanceof.
Unless you are using a generic factory, at the moment when you create a GameObject you know what concrete type it is. So what you can do is pass any GameGroups you create an observable object, and allow them to add listeners to it. It would work like this:
public class Game {
private void makeAGameGroup() {
mGameObjects.add(new GameGroup(mUITweenManagerInformer));
}
private void allocateUITweenManager() {
mUITweenManagerInformer.fire(mUITweenManager);
}
private class OurUITweenManagerInformer extends UITweenManagerInformer {
private ArrayList<UITweenManagerListener> listeners;
public void addUITweenManagerListener(UITweenManagerListener l) {
listeners.add(l);
}
public void fire(UITweenManager next) {
for (UITweenManagerListener l : listeners)
l.changed(next);
}
}
private OurUITweenManagerInformer mUITweenManagerInformer = new OurUITweenManagerInformer();
}
public interface UITweenManagerInformer {
public void addUITweenManagerListener(UITweenManagerListener l);
}
public interface UITweenManagerListener {
public void changed(UITweenManager next);
}
What draws me to this solution is:
Because a UITweenManagerInformer is a constructor parameter to GameGoup, you cannot forget to pass it one, whereas with an instance method you might forget to call it.
It makes intuitive sense to me that information that an object needs (like the way a GameGroup needs knowledge of the current UITweenManager) should be passed as a constructor parameter -- I like to think of these as prerequisites for an object existing. If you don't have knowledge of the current UITweenManager, you shouldn't create a GameGroup, and this solution enforces that.
instanceof is never used.
I have the following modeling problem:
as an exercise, I need to model a system that allocates units (police cars/fire trucks) to a specific emergency (fire/robbery/...). Therefore an emergency needs to say how many units it needs (for instance 2 fire trucks and 3 ambulances). Of course, these units need to be assigned to that emergency. I've modeled this as two abstract classes: Emergency and Unit with the real units and emergencies that inherit these classes.
Is there an elegant design so the emergency can tell in a generic way which units it needs (additional types of units and emergencies are expected)?
The programming language is Java.
I know this is probably one of the standard design patterns, but I'm quite new to these design patterns.
You have a lot of options with this. Some of the patterns that come to mind are Observer, Chain of Responsibility, and Visitor. However, a lot of non-pattern solutions seem reasonable too. Don't be hypnotized into using patterns all the time.
That being said, a combination of patterns will probably be the best solution. Create a higher level class, some sort of a Director. Allow the Director to observe the Emergencies, using the Observer pattern. When the Director receives a work request, it goes to an Object Pool and modifies the Emergency as it sees fit.
What about good ol' Java interface?
public interface HasEmergency {
public UnitType responderUnit();
public int numberOfUnitsNeeded();
}
public abstract class Resource implements HasEmergency {
// ...
}
I keep hearing the statement on most programming related sites:
Program to an interface and not to an Implementation
However I don't understand the implications?
Examples would help.
EDIT: I have received a lot of good answers even so could you'll supplement it with some snippets of code for a better understanding of the subject. Thanks!
You are probably looking for something like this:
public static void main(String... args) {
// do this - declare the variable to be of type Set, which is an interface
Set buddies = new HashSet();
// don't do this - you declare the variable to have a fixed type
HashSet buddies2 = new HashSet();
}
Why is it considered good to do it the first way? Let's say later on you decide you need to use a different data structure, say a LinkedHashSet, in order to take advantage of the LinkedHashSet's functionality. The code has to be changed like so:
public static void main(String... args) {
// do this - declare the variable to be of type Set, which is an interface
Set buddies = new LinkedHashSet(); // <- change the constructor call
// don't do this - you declare the variable to have a fixed type
// this you have to change both the variable type and the constructor call
// HashSet buddies2 = new HashSet(); // old version
LinkedHashSet buddies2 = new LinkedHashSet();
}
This doesn't seem so bad, right? But what if you wrote getters the same way?
public HashSet getBuddies() {
return buddies;
}
This would have to be changed, too!
public LinkedHashSet getBuddies() {
return buddies;
}
Hopefully you see, even with a small program like this you have far-reaching implications on what you declare the type of the variable to be. With objects going back and forth so much it definitely helps make the program easier to code and maintain if you just rely on a variable being declared as an interface, not as a specific implementation of that interface (in this case, declare it to be a Set, not a LinkedHashSet or whatever). It can be just this:
public Set getBuddies() {
return buddies;
}
There's another benefit too, in that (well at least for me) the difference helps me design a program better. But hopefully my examples give you some idea... hope it helps.
One day, a junior programmer was instructed by his boss to write an application to analyze business data and condense it all in pretty reports with metrics, graphs and all that stuff. The boss gave him an XML file with the remark "here's some example business data".
The programmer started coding. A few weeks later he felt that the metrics and graphs and stuff were pretty enough to satisfy the boss, and he presented his work. "That's great" said the boss, "but can it also show business data from this SQL database we have?".
The programmer went back to coding. There was code for reading business data from XML sprinkled throughout his application. He rewrote all those snippets, wrapping them with an "if" condition:
if (dataType == "XML")
{
... read a piece of XML data ...
}
else
{
.. query something from the SQL database ...
}
When presented with the new iteration of the software, the boss replied: "That's great, but can it also report on business data from this web service?" Remembering all those tedious if statements he would have to rewrite AGAIN, the programmer became enraged. "First xml, then SQL, now web services! What is the REAL source of business data?"
The boss replied: "Anything that can provide it"
At that moment, the programmer was enlightened.
An interface defines the methods an object is commited to respond.
When you code to the interface, you can change the underlying object and your code will still work ( because your code is agnostic of WHO do perform the job or HOW the job is performed ) You gain flexibility this way.
When you code to a particular implementation, if you need to change the underlying object your code will most likely break, because the new object may not respond to the same methods.
So to put a clear example:
If you need to hold a number of objects you might have decided to use a Vector.
If you need to access the first object of the Vector you could write:
Vector items = new Vector();
// fill it
Object first = items.firstElement();
So far so good.
Later you decided that because for "some" reason you need to change the implementation ( let's say the Vector creates a bottleneck due to excessive synchronization)
You realize you need to use an ArrayList instad.
Well, you code will break ...
ArrayList items = new ArrayList();
// fill it
Object first = items.firstElement(); // compile time error.
You can't. This line and all those line who use the firstElement() method would break.
If you need specific behavior and you definitely need this method, it might be ok ( although you won't be able to change the implementation ) But if what you need is to simply retrieve the first element ( that is , there is nothing special with the Vector other that it has the firstElement() method ) then using the interface rather than the implementation would give you the flexibility to change.
List items = new Vector();
// fill it
Object first = items.get( 0 ); //
In this form you are not coding to the get method of Vector, but to the get method of List.
It does not matter how do the underlying object performs the method, as long as it respond to the contract of "get the 0th element of the collection"
This way you may later change it to any other implementation:
List items = new ArrayList(); // Or LinkedList or any other who implements List
// fill it
Object first = items.get( 0 ); // Doesn't break
This sample might look naive, but is the base on which OO technology is based ( even on those language which are not statically typed like Python, Ruby, Smalltalk, Objective-C etc )
A more complex example is the way JDBC works. You can change the driver, but most of your call will work the same way. For instance you could use the standard driver for oracle databases or you could use one more sophisticated like the ones Weblogic or Webpshere provide . Of course it isn't magical you still have to test your product before, but at least you don't have stuff like:
statement.executeOracle9iSomething();
vs
statement.executeOracle11gSomething();
Something similar happens with Java Swing.
Additional reading:
Design Principles from Design Patterns
Effective Java Item: Refer to objects by their interfaces
( Buying this book the one of the best things you could do in life - and read if of course - )
My initial read of that statement is very different than any answer I've read yet. I agree with all the people that say using interface types for your method params, etc are very important, but that's not what this statement means to me.
My take is that it's telling you to write code that only depends on what the interface (in this case, I'm using "interface" to mean exposed methods of either a class or interface type) you're using says it does in the documentation. This is the opposite of writing code that depends on the implementation details of the functions you're calling. You should treat all function calls as black boxes (you can make exceptions to this if both functions are methods of the same class, but ideally it is maintained at all times).
Example: suppose there is a Screen class that has Draw(image) and Clear() methods on it. The documentation says something like "the draw method draws the specified image on the screen" and "the clear method clears the screen". If you wanted to display images sequentially, the correct way to do so would be to repeatedly call Clear() followed by Draw(). That would be coding to the interface. If you're coding to the implementation, you might do something like only calling the Draw() method because you know from looking at the implementation of Draw() that it internally calls Clear() before doing any drawing. This is bad because you're now dependent on implementation details that you can't know from looking at the exposed interface.
I look forward to seeing if anyone else shares this interpretation of the phrase in the OP's question, or if I'm entirely off base...
It's a way to separate responsibilities / dependancies between modules.
By defining a particular Interface (an API), you ensure that the modules on either side of the interface won't "bother" one another.
For example, say module 1 will take care of displaying bank account info for a particular user, and module2 will fetch bank account info from "whatever" back-end is used.
By defining a few types and functions, along with the associated parameters, for example a structure defining a bank transaction, and a few methods (functions) like GetLastTransactions(AccountNumber, NbTransactionsWanted, ArrayToReturnTheseRec) and GetBalance(AccountNumer), the Module1 will be able to get the needed info, and not worry about how this info is stored or calculated or whatever. Conversely, the Module2 will just respond to the methods call by providing the info as per the defined interface, but won't worry about where this info is to be displayed, printed or whatever...
When a module is changed, the implementation of the interface may vary, but as long as the interface remains the same, the modules using the API may at worst need to be recompiled/rebuilt, but they do not need to have their logic modified in anyway.
That's the idea of an API.
At its core, this statement is really about dependencies. If I code my class Foo to an implementation (Bar instead of IBar) then Foo is now dependent on Bar. But if I code my class Foo to an interface (IBar instead of Bar) then the implementation can vary and Foo is no longer dependent on a specific implementation. This approach gives a flexible, loosely-coupled code base that is more easily reused, refactored and unit tested.
Take a red 2x4 Lego block and attach it to a blue 2x4 Lego block so one sits atop the other. Now remove the blue block and replace it with a yellow 2x4 Lego block. Notice that the red block did not have to change even though the "implementation" of the attached block varied.
Now go get some other kind of block that does not share the Lego "interface". Try to attach it to the red 2x4 Lego. To make this happen, you will need to change either the Lego or the other block, perhaps by cutting away some plastic or adding new plastic or glue. Notice that by varying the "implementation" you are forced to change it or the client.
Being able to let implementations vary without changing the client or the server - that is what it means to program to interfaces.
An interface is like a contract between you and the person who made the interface that your code will carry out what they request. Furthermore, you want to code things in such a way that your solution can solve the problem many times over. Think code re-use. When you are coding to an implementation, you are thinking purely of the instance of a problem that you are trying to solve. So when under this influence, your solutions will be less generic and more focused. That will make writing a general solution that abides by an interface much more challenging.
Look, I didn't realize this was for Java, and my code is based on C#, but I believe it provides the point.
Every car have doors.
But not every door act the same, like in UK the taxi doors are backwards. One universal fact is that they "Open" and "Close".
interface IDoor
{
void Open();
void Close();
}
class BackwardDoor : IDoor
{
public void Open()
{
// code to make the door open the "wrong way".
}
public void Close()
{
// code to make the door close properly.
}
}
class RegularDoor : IDoor
{
public void Open()
{
// code to make the door open the "proper way"
}
public void Close()
{
// code to make the door close properly.
}
}
class RedUkTaxiDoor : BackwardDoor
{
public Color Color
{
get
{
return Color.Red;
}
}
}
If you are a car door repairer, you dont care how the door looks, or if it opens one way or the other way. Your only requirement is that the door acts like a door, such as IDoor.
class DoorRepairer
{
public void Repair(IDoor door)
{
door.Open();
// Do stuff inside the car.
door.Close();
}
}
The Repairer can handle RedUkTaxiDoor, RegularDoor and BackwardDoor. And any other type of doors, such as truck doors, limousine doors.
DoorRepairer repairer = new DoorRepairer();
repairer.Repair( new RegularDoor() );
repairer.Repair( new BackwardDoor() );
repairer.Repair( new RedUkTaxiDoor() );
Apply this for lists, you have LinkedList, Stack, Queue, the normal List, and if you want your own, MyList. They all implement the IList interface, which requires them to implement Add and Remove. So if your class add or remove items in any given list...
class ListAdder
{
public void PopulateWithSomething(IList list)
{
list.Add("one");
list.Add("two");
}
}
Stack stack = new Stack();
Queue queue = new Queue();
ListAdder la = new ListAdder()
la.PopulateWithSomething(stack);
la.PopulateWithSomething(queue);
Allen Holub wrote a great article for JavaWorld in 2003 on this topic called Why extends is evil. His take on the "program to the interface" statement, as you can gather from his title, is that you should happily implement interfaces, but very rarely use the extends keyword to subclass. He points to, among other things, what is known as the fragile base-class problem. From Wikipedia:
a fundamental architectural problem of object-oriented programming systems where base classes (superclasses) are considered "fragile" because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class.
In addition to the other answers, I add more:
You program to an interface because it's easier to handle. The interface encapsulates the behavior of the underlying class. This way, the class is a blackbox. Your whole real life is programming to an interface. When you use a tv, a car, a stereo, you are acting on its interface, not on its implementation details, and you assume that if implementation changes (e.g. diesel engine or gas) the interface remains the same. Programming to an interface allows you to preserve your behavior when non-disruptive details are changed, optimized, or fixed. This simplifies also the task of documenting, learning, and using.
Also, programming to an interface allows you to delineate what is the behavior of your code before even writing it. You expect a class to do something. You can test this something even before you write the actual code that does it. When your interface is clean and done, and you like interacting with it, you can write the actual code that does things.
"Program to an interface" can be more flexible.
For example, we are writing a class Printer which provides print service. currently there are 2 class (Cat and Dog) need to be printed. So we write code like below
class Printer
{
public void PrintCat(Cat cat)
{
...
}
public void PrintDog(Dog dog)
{
...
}
...
}
How about if there is a new class Bird also needs this print service? We have to change Printer class to add a new method PrintBird(). In real case, when we develop Printer class, we may have no idea about who will use it. So how to write Printer? Program to an interface can help, see below code
class Printer
{
public void Print(Printable p)
{
Bitmap bitmap = p.GetBitmap();
// print bitmap ...
}
}
With this new Printer, everything can be printed as long as it implements Interface Printable. Here method GetBitmap() is just a example. The key thing is to expose an Interface not a implementation.
Hope it's helpful.
Essentially, interfaces are the slightly more concrete representation of general concepts of interoperation - they provide the specification for what all the various options you might care to "plug in" for a particular function should do similarly so that code which uses them won't be dependent on one particular option.
For instance, many DB libraries act as interfaces in that they can operate with many different actual DBs (MSSQL, MySQL, PostgreSQL, SQLite, etc.) without the code that uses the DB library having to change at all.
Overall, it allows you to create code that's more flexible - giving your clients more options on how they use it, and also potentially allowing you to more easily reuse code in multiple places instead of having to write new specialized code.
By programming to an interface, you are more likely to apply the low coupling / high cohesion principle.
By programming to an interface, you can easily switch the implementation of that interface (the specific class).
It means that your variables, properties, parameters and return types should have an interface type instead of a concrete implementation.
Which means you use IEnumerable<T> Foo(IList mylist) instead of ArrayList Foo(ArrayList myList) for example.
Use the implementation only when constructing the object:
IList list = new ArrayList();
If you have done this you can later change the object type maybe you want to use LinkedList instead of ArrayList later on, this is no problem since everywhere else you refer to it as just "IList"
It's basically where you make a method/interface like this: create( 'apple' ) where the method create(param) comes from an abstract class/interface fruit that is later implemented by concrete classes. This is different than subclassing. You are creating a contract that classes must fulfill. This also reduces coupling and making things more flexible where each concrete class implements it differently.
The client code remains unaware of the specific types of objects used and remains unaware of the classes that implement these objects. Client code only knows about the interface create(param) and it uses it to make fruit objects. It's like saying, "I don't care how you get it or make it I, just want you to give it to me."
An analogy to this is a set of on and off buttons. That is an interface on() and off(). You can use these buttons on several devices, a TV, radio, light. They all handle them differently but we don't care about that, all we care about is to turn it on or turn it off.
Coding to an interface is a philosophy, rather than specific language constructs or design patterns - it instructs you what is the correct order of steps to follow in order to create better software systems (e.g. more resilient, more testable, more scalable, more extendible, and other nice traits).
What it actually means is:
===
Before jumping to implementations and coding (the HOW) - think of the WHAT:
What black boxes should make up your system,
What is each box' responsibility,
What are the ways each "client" (that is, one of those other boxes, 3rd party "boxes", or even humans) should communicate with it (the API of each box).
After you figure the above, go ahead and implement those boxes (the HOW).
Thinking first of what a box' is and what its API, leads the developer to distil the box' responsibility, and to mark for himself and future developers the difference between what is its exposed details ("API") and it's hidden details ("implementation details"), which is a very important differentiation to have.
One immediate and easily noticeable gain is the team can then change and improve implementations without affecting the general architecture. It also makes the system MUCH more testable (it goes well with the TDD approach).
===
Beyond the traits I've mentioned above, you also save A LOT OF TIME going this direction.
Micro Services and DDD, when done right, are great examples of "Coding to an interface", however the concept wins in every pattern from monoliths to "serverless", from BE to FE, from OOP to functional, etc....
I strongly recommend this approach for Software Engineering (and I basically believe it makes total sense in other fields as well).