I have came across several cases where I have a parent object with multiple objects, and where changes to information in one child object affects others.
For example, consider the following case:
interface IUniverse
{
IStorage ShirtStorage;
IList<IHuman> Humans;
}
Interface IStorage:
{
string Location;
int Capacity;
IList<IShirt> Items;
}
Interface IHuman
{
string Name;
int Age;
IList<IShirt> Shirts;
}
I would like to remove a particular shirt from ShirtStorage in my universe, but at the same time, since the shirt is removed from existence, it should be removed from all humans as well.
I have thought of 3 ways to do this:
Firstly, we can introduce Add(IClothing) and Remove(IClothing) methods to IStorage<T> and IHuman.
interface IUniverse
{
IStorage ShirtStorage;
IList<IHuman> Humans;
}
Interface IStorage
{
string Location;
int Capacity;
IList<IShirt> Items;
**void Add(IShirt);**
**void Remove(IShirt);**
}
Interface IHuman
{
string Name;
int Age;
IList<IShirt> Shirts;
**void AddShirts(IShirt);**
**void RemoveShirts(IShirts);**
}
Afterwards, the implementations of above interfaces will not have anything under the hood which removes a particular shirt from all humans when it is removed from ShirtStorage.
The disadvantage of this design is that each time a programmer removes a shirt from the universe, he will have to manually remove every single reference from each human.
That is to say, the programmer has to know the exact structure of the universe in order to remove a single shirt. In the event where the structure of the universe becomes highly complex, such that references to a particular shirt may appear more than just in IHuman, this may prove to be erroneous and tedious.
Secondly, we similarly introduce Add(IShirt) and Remove(IShirt) methods to the interfaces IStorage and IHuman:
interface IUniverse
{
IStorage<IShirt> ShirtStorage;
IList<IHuman> Humans;
}
Interface IStorage
{
string Location;
int Capacity;
IList<IShirt> Items;
**void Add(IShirt);**
**void Remove(IShirt);**
}
Interface IHuman
{
string Name;
int Age;
IList<ICShirt> Shirts;
**void AddShirt(IShirt);**
**void RemoveShirt(IShirt);**
}
.. however this time round, we use an implementation of the above interfaces such that there is some notification going on under the hood. That is to say,
class Storage : IStorage
{
IUniverse parentUniverse;
string Location;
int Capacity;
IList<IShirt> Items;
// ... Implementation for Add(IShirt item) is trivial
void Remove(IShirt item)
{
this.Items.Add(item);
foreach (IHuman human in this.parentUniverse)
foreach(IClothing clothing in human.Clothings)
if (clothing == item)
human.RemoveClothing(clothing);
}
}
Indeed, by placing all the notification in the implementation of the interface, consumers of the interface will not have to go through every single possible reference to a particular IShirt when he wants to remove it from existence, thus making it better in this sense as compared to the previous solution.
However, the disadvantage is that such a design inherently leads to pathological lying, and violates the Single Responsibility Principle as well. If the programmer calls Remove(IShirt) on ShirtStorage, he wouldn't be aware of what reference is being removed from where.
If said programmer wishes to write a GUI using the Mediator pattern for example, he would be unsure of which notification message to send out.
Which humans exactly have shirts removed from them, thereby requiring an update on the GUI for some component which reflects the list of shirts belonging to a particular human? What if I have a Catalog class with names of all the shirts - wouldn't the entry corresponding to removed shirt be removed as well (under the hood)? Would I also have to update the corresponding GUI component for my catalogs?
Thirdly, we introduce the Add(IShirt) and Remove(IShirt) methods to IUniverse instead:
interface IUniverse
{
IStorage ShirtStorage;
IList<IHuman> Humans;
void Add(IShirt);
void Remove(IShirt);
}
Interface IStorage:
{
string Location;
int Capacity;
IList<IShirt> Items;
}
Interface IHuman
{
string Name;
int Age;
IList<IShirt> Shirts;
}
By doing so, we force consumers of the interface to accept that removing a shirt affects not just the shirt storage, but other members of IUniverse as well.
However, the disadvantages are like those in the second solution. On top of that, IUniverse instances eventually become somewhat of a God Object. Every place where I need to remove a shirt from a universe, I have to have a reference to the universe.
If a particular GUI component simply wants to display information for a ShirtStorage and to allow for interaction with the storage (i.e. adding and removing of shirts), wouldn't this introduce some coupling between the GUI component and the Universe, when the only coupling that should exists is that of the GUI component and IStorage?
I have wrote several applications which have used a mix of all three solutions. Indeed some solutions seem better than others in different cases, but the inconsistencies are a pain because I almost always forgot to do certain things when switching from one design to another.
Every time I hear the phrase "Propagating Changes" in the context of oop, I immediately think Observer pattern. So instead of giving the responsibility to your domain objects to "synchronize" adding and removing shirts, I would introduce another class that takes over this responsibility, and have your domain objects raise relevant events. And you also keep adhering to the Single Responsibility Principle.
HTH
Related
I am making a simple turn-based farming simulator game where players make choices whether to buy land or crops and have turn-count based growing. Different crops grow for different times, and have different purchase prices and sale values. Objective is to be the first to reach a dollar amount.
My question is how to develop these crops programmatically. I currently have each crop variation as a subclass of a Crop, however, this leads to a lot of redundancy (mostly different field/attribute values, or image paths). Since these objects are very similar save for some values, should they be subclasses, or would it be better practice to make one class Crop with an Enum of type and use logic to determine the values it should have?
Superclass Crop
subclass Wheat
subclass Corn
subclass Barley
Or
Crop.Type = CropType.Wheat
if(this.Type == CropType.Wheat) { return StockMarket.Wheat_Sell_Value; }
else if(this.Type == CropType.Corn) { return StockMarket.Corn_Sell_Value; }
If you make a single crop class it risks becoming very large and unwieldly, especially if you want to add a new crop type you'll have to update the 100's of if statements littered through your code (e.g. if(this.Type == CropType.Wheat) { return StockMarket.Wheat_Sell_Value; }).
To echo #oswin's answer, use inheritance sparingly. You are probably ok using a base-class with a few "dumb" properties, but be especially careful when adding anything that implements "behaviour" or complexity, like methods and logic; i.e. anything that acts on CropType within Crop is probably a bad idea.
One simple approach is if crop types all have the same properties, but just different values; and so crop instances just get acted on by processes within the game, see below. (Note: If crops have different properties then I would probably use interfaces to handle that because they are more forgiving when you need to make changes).
// Crop Types - could he held in a database or config file, so easy to add new types.
// Water, light, heat are required to grow and influence how crops grow.
// Energy - how much energy you get from eating the crop.
Name:Barley, growthRate:1.3, water:1.3, light:1.9, heat:1.3, energy:1.4
Name:Corn, growthRate:1.2, water:1.2, light:1.6, heat:1.2, energy:1.5
Name:Rice, growthRate:1.9, water:1.5, light:1.0, heat:1.4, energy:1.8
The crop type values help drive logic later on. You also (I assume) need crop instance:
class CropInstance
{
public CropType Crop { get; set; }
public double Size { get; set; }
public double Health { get; }
}
Then you simply have other parts of your program that act on instances of Crop, e.g:
void ApplyWeatherForTurn(CropInstance crop, Weather weather)
{
// Logic that applies weather to a crop for the turn.
// E.g. might under or over supply the amount of water, light, heat
// depending on the type of crop, resulting in 'x' value, which might
// increase of decrease the health of the crop instance.
double x = crop.WaterRequired - weather.RainFall;
// ...
crop.Health = x;
}
double CurrentValue(CropInstance crop)
{
return crop.Size * crop.Health * crop.Crop.Energy;
}
Note you can still add logic that does different things to different crops, but based on their values, not their types:
double CropThieves(CropInstance crop)
{
if(crop.health > 2.0 & crop.Crop.Energy > 2.0)
{
// Thieves steal % of crop.
crop.Size = crop.Size * 0.9;
}
}
Update - Interfaces:
I was thinking about this some more. The assumption with code like double CurrentValue(CropInstance crop) is that it assumes you only deal in crop instances. If you were to add other types like Livestock that sort of code could get cumbersome.
E.g. If you know for certain that you'll only ever have crops then the approach is fine. If you decide to add another type later, it will be manageable, if you become wildly popular and decide to add 20 new types you'll want to do a re-write / re-architecture because it won't scale well from a maintenance perspective.
This is where interfaces come in, imagine you will eventually have many different types including Crop (as above) and Livestock - note it's properties aren't the same:
// growthRate - how effectively an animal grows.
// bredRate - how effectively the animals bred.
Name:Sheep, growthRate:2.1, water:1.9, food:2.0, energy:4.6, bredRate:1.7
Name:Cows, growthRate:1.4, water:3.2, food:5.1, energy:8.1, breedRate:1.1
class HerdInstance
{
public HerdType Herd { get; set; }
public int Population { get; set; }
public double Health { get; }
}
So how would interfaces come to the rescue? Crop and herd specific logic is located in the relevant instance code:
// Allows items to be valued
interface IFinancialValue
{
double CurrentValue();
}
class CropInstance : IFinancialValue
{
...
public double CurrentValue()
{
return this.Size * this.Health * this.Crop.Energy;
}
}
class HerdInstance : IFinancialValue
{
...
public double CurrentValue()
{
return this.Population * this.Health * this.Herd.Energy - this.Herd.Food;
}
}
You can then do things with objects that implement IFinancialValue:
public string NetWorth()
{
List<IFinancialValue> list = new List<IFinancialValue>();
list.AddRange(Crops);
list.AddRange(Herds);
double total = 0.0;
for(int i = 0; i < list.Count; i++)
{
total = total + list[i].CurrentValue();
}
return string.Format("Your total net worth is ${0} from {1} sellable assets", total, list.Count);
}
You might recall that above I said:
...but be especially careful when adding anything that implements
"behaviour" or complexity, like methods and logic; i.e. anything that
acts on CropType within Crop is probably a bad idea.
...which seems to contradict the code just above. The difference is that if you have one class that has everything in it you won't be able to flex, where as in the approach above I have assumed that I can add as many different game-asset types as I like by using the [x]Type and [x]Instance architecture.
The answer depends on the difference in functionality between the crop types. The general rule is to avoid unnecessary complexity where possible and inheritance should be used sparingly because it introduces hard dependencies.
So if all crops are functionally similar and only differ by their attribute values then you would want to use a single class for crop, but if your game logic demands the crop types to behave very differently and/or carry very different sets of data, then you may want to consider creating separate structures.
If inheritance would be the best choice (in case you need separate structures) cannot be answered without knowing the exact details of your game world either. Some alternatives you could consider are:
interfaces (or another type of mix-in), which allows you to re-use behavior or data across multiple types, e.g. if crops can be harvested, maybe forests can be harvested as well.
structs (or data-classes), which only define the data structure and not the behavior. This is generally more efficient and forces you to do a simpler design with less abstractions.
a functional programming approach where the crops only exist as primitives being passed around functions. This has all the benefits of functional programming, such as no side effects, less bugs, easier to write tests, easier concurrency designs which can help your game scale larger.
I'm relatively new to this site so if I am doing something wrong when it comes to posting questions and whatnot please let me know so I can fix it for next time.
I'm curious as to whether or not it is bad OOP practice to subclass multiple classes from a single base class. That probably doesn't quite make sense so I'm going to elaborate a little bit.
Say for instance you are designing a game and you have several different monsters you might come across. The approach I would take is to have a base abstract class for just a general monster object and then subclass all of the specific types of monsters from the base class using a new class.
One of my instructors told me that you shouldn't rely on inheritance in this case because the number of monsters will continue to grow and grow and the number of classes will increase to a point where it is hard to keep track of all of them and thus yo will have to recompile the program with every new class added in the future.
I don't understand why (or even if) that's a bad thing. If anybody could help me understand where my professor is coming from that would be much appreciated.
Thanks!
If monsters are very similar, in that the only differences are (for example) their name, how much damage they impart, what color they are, etc., then these differences which can be reflected in a field (in values), may make sub-classing unnecessary.
If, however, you have monsters that are fundamentally different from others, such that it is necessary to have very different methods and logic, and more specifically, differences that cannot be reflected in fields, then a sub-class SpecialMonster may be necessary.
But again, even SpecialMonster may not need to be sub-classed by individual monster types, as it's fields may be enough to distinguish between them.
While it's legal to have a million sub-classes of specific monster types, you don't want to take care of all that duplicate code when it could simply be expressed in the fields of new Monster instances, such as
new Monster("Goob", WakeTime.NOCTURNAL, 35, new Weapon[]{sword, hammer, knittingNeedle});
new Monster("Mister Mxyzptlk", WakeTime.ANYTIME, 71, new Weapon[]{sword, mindMeld, cardboardCutter});
There is an alternative, where you do have a lot of classes, but you don't impose them onto your users, and you don't clutter up your API/JavaDoc with them. If your Monster happens to be an abstract class
public abstract class Monster {
private final String name;
...
public Monster(String name, int default_damage, WakeTime wake_time, Weapon[] weapons) {
this.name = name;
...
}
public String getName() {
return name;
}
...
public abstract int getDamage(int hit_strength);
}
Then you could have a Monster convenience creator like this:
/**
<P>Convenience functions for creating new monsters of a specific type.</P>
**/
public class NewMonsterOfType {
private NewMonsterOfType() {
throw new IllegalStateException("Do not instantiate.");
}
/**
<P>Creates a new monster that is nocturnal, has 35-default-damage, and whose weapens are: sword, hammer, knittingNeedle.</P>
**/
public static final GOOB = new GoobMonster();
/**
<P>Creates a new monster that can be awake at any time, has 71-default-damage, and whose weapens are: sword, mindMeld, cardboardCutter.</P>
**/
public static final MISTER_MXYZPTLK = new MisterMxyzptlkMonster();
}
class GoobMonster extends Monster {
public GoobMonster() {
super("Goob", WakeTime.NOCTURNAL, 35, new Weapon[]{sword, hammer, knittingNeedle});
}
public int getDamage(int hit_strength) {
return (hit_strength < 70) ? getDefaultDamage() : (getDefaultDamage() * 2);
}
}
class MisterMxyzptlkMonster extends Monster {
public GoobMonster() {
super("Mister Mxyzptlk", WakeTime.ANYTIME, 71, new Weapon[]{sword, mindMeld, cardboardCutter});
}
public int getDamage(int hit_strength) {
return (hit_strength < 160) ? getDefaultDamage() + 10 : (getDefaultDamage() * 3);
}
}
In order for these private (actually package-protected) classes to not show up in you JavaDoc, you need to set its access to something either protected or public.
Inheritance is quite natural in your scenario as all the specific monsters ARE base monsters as well :). I'd actually use inheritance a lot here, since probably specific monsters do have specific behaviour that would have to be overriden. MonsterA might move by crawling while MonsterB might move by flying. The base AMonster would have an abstract Move() method , implemented by those sub types.
This isn't a final answer, it really much depends on the game needs, however, in simplified form, inheritance makes sense here. The number of monster types might continue to grow, but really, are they all the same? The monster design is just based on grouping together some predefined data/behaviour? The game is quite trivial then...
I really get the impression your instructor doesn't code games for a living (me neither, although I did make a game some time ago), but his explanation why you shouldn't use inheritance is way too simplified. The number of defined classes is never an issue in an app, the more the better IF the Single Responsibility Principle is respected.
About you have to recompile your app.... yeah, when you fix a bug you have to recompile it too. IMO, the reasons he gave to you aren't valid for this scenario. He needs to come up with much better arguments.
In the mean time, go for inheritance.
Theoretical question needs theoretical answer :).
It is not just bad, it is pointless. You should have a LIMITED number of "base" classes that inherits from other classes, and those classes should be composed from other classes (vide favour composition versus inheritance).
So as complexity grows the number of classes that base classes are composed from should grows. Not number of base classes itself.
It is like in the industry. If you see machines for instance, they are really composed from large quantity of small parts, and some of those small parts are the same in different machines. When yo designing new machine you do not order new unique "base" part for it just to have a name for your new machine. You use parts existing on a market and you designing some new parts (not "base") only if you cannot find existing counterparts...
This may not be the best kind of question suited to stackoverflow, but I'm only after an answer that best describes why programmers sometimes don't use setters/getters for properties, e.g. in the case of property injection (DI).
Consider this example...
class Test
{
public propertyA;
protected propertyB;
public function setPropertyB(val)
{
// do some logic to validate 'val'
this.propertyB = val;
}
public function getPropertyB()
{
return this.propertyB;
}
}
Why would you choose the style of directly setting propertyA:
var Test = new Test();
Test.propertyA = 1;
Over the setter option for propertyB:
var Test = new Test();
Test.setPropertyB(1);
I always use the setter/getter approach, but I have seen some pretty established frameworks using the propertyA approach interspersed with the propertyB approach. What benefits do we have using this method?
Why you might not care about encapsulation:
You might be throwing away the project 15 minutes later.
You might have found getters/setters to be bottlenecks for your CPU-bound code, causing you to optimize for performance instead of design.
The instance field might be immutable and read-only, so there might be no danger in exposing it.
You're too lazy to write getters/setters.
You should use getters and setters because they allow you to control the interface to your objects.
For example, let's say I have a bank account class in a Java application:
class BankAccount {
private int balance;
BankAccount() {
balance = 0;
}
public void deposit(int amount) {
balance = balance + amount;
}
public void withdraw(int amount) {
balance = balance - amount;
}
}
When my software needs to alter a bank account's balance through deposits and withdrawals, it calls the appropriate methods.
Now, along comes some sneaky individual who manages to figure out that they can increase their bank balance by telling their internet banking software to withdraw negative amounts of money. I can fix this bug by adding a precondition to the withdraw method, and the bug goes away.
If the balance field was instead public, and a whole bunch of classes were just manipulating it's value arbitrarily, those classes would now need to be changed. If some of those external classes were written by third parties, then we're looking at a whole lot of pain to get the bug fixed.
Why would you use public fields? In the general case, you probably shouldn't. Some languages allow you to have a field scoped as public, then if you need to add a getter/setter later on you can do so without changing your object's interface (I believe C# does this, but correct me if I'm wrong).
This is quite a common problem I run into. Let's hear your solutions. I'm going to use an Employee-managing application as an example:-
We've got some entity classes, some of which implement a particular interface.
public interface IEmployee { ... }
public interface IRecievesBonus { int Amount { get; } }
public class Manager : IEmployee, IRecievesBonus { ... }
public class Grunt : IEmployee /* This company sucks! */ { ... }
We've got a collection of Employees that we can iterate over. We need to grab all the objects that implement IRecievesBonus and pay the bonus.
The naive implementation goes something along the lines of:-
foreach(Employee employee in employees)
{
IRecievesBonus bonusReciever = employee as IRecievesBonus;
if(bonusReciever != null)
{
PayBonus(bonusReciever);
}
}
or alternately in C#:-
foreach(IRecievesBonus bonusReciever in employees.OfType<IRecievesBonus>())
{
PayBonus(bonusReciever);
}
We cannot modify the IEmployee interface to include details of the child type as we don't want to pollute the super-type with details that only the sub-type cares about.
We do not have an existing collection of only the subtype.
We cannot use the Visitor pattern because the element types are not stable. Also, we might have a type which implements both IRecievesBonus and IDrinksTea. Its Accept method would contain an ambiguous call to visitor.Visit(this).
Often we're forced down this route because we can't modify the super-type, nor the collection e.g. in .NET we may need to find all the Buttons on this Form via the child Controls collection. We may need to do something to the child types that depends on some aspect of the child type (e.g. the bonus amount in the example above).
Strikes me as odd that there isn't an "accepted" way to do this, given how often it comes up.
1) Is the type conversion worth avoiding?
2) Are there any alternatives I haven't thought of?
EDIT
Péter Török suggests composing Employee and pushing the type conversion further down the object tree:-
public interface IEmployee
{
public IList<IEmployeeProperty> Properties { get; }
}
public interface IEmployeeProperty { ... }
public class DrinksTeaProperty : IEmployeeProperty
{
int Sugars { get; set; }
bool Milk { get; set; }
}
foreach (IEmployee employee in employees)
{
foreach (IEmployeeProperty property in employee.Propeties)
{
// Handle duplicate properties if you need to.
// Since this is just an example, we'll just
// let the greedy ones have two cups of tea.
DrinksTeaProperty tea = property as DrinksTeaProperty;
if (tea != null)
{
MakeTea(tea.Sugers, tea.Milk);
}
}
}
In this example it's definitely worth pushing these traits out of the Employee type - particularly because some managers might drink tea and some might not - but we still have the same underlying problem of the type conversion.
Is it the case that it's "ok" so long as we do it at the right level? Or are we just moving the problem around?
The holy grail would be a variant on the Visitor pattern where:-
You can add element members without modifying all the visitors
Visitors should only visit types they're interested in visiting
The visitor can visit the member based on an interface type
Elements might implement multiple interfaces which are visited by different visitors
Doesn't involve casting or reflection
but I appreciate that's probably unrealistic.
I would definitely try to resolve this with composition instead of inheritance, by associating the needed properties/traits to Employee, instead of subclassing it.
I can give an example partly in Java, I think it's close enough to your language (C#) to be useful.
public enum EmployeeProperty {
RECEIVES_BONUS,
DRINKS_TEA,
...
}
public class Employee {
Set<EmployeeProperty> properties;
// methods to add/remove/query properties
...
}
And the modified loop would look like this:
foreach(Employee employee in employees) {
if (employee.getProperties().contains(EmployeeProperty.RECEIVES_BONUS)) {
PayBonus(employee);
}
}
This solution is much more flexible than subclassing:
it can trivially handle any combination of employee properties, while with subclassing you would experience a combinatorial explosion of subclasses as the number of properties grow,
it trivially allows you to change Employee properties runtime, while with subclassing this would require changing the concrete class of your object!
In Java, enums can have properties or (even virtual) methods themselves - I don't know whether this is possible in C#, but in the worst case, if you need more complex properties, you can implement them with a class hierarchy. (Even in this case, you are not back to square one, since you have an extra level of indirection which gives you the flexibility described above.)
Update
You are right that in the most general case (discussed in the last sentence above) the type conversion problem is not resolved, just pushed one level down on the object graph.
In general, I don't know a really satisfying solution to this problem. The typical way to handle it is using polymorphism: pull up the common interface and manipulate the objects via that, thus eliminating the need for downcasts. However, in cases when the objects in question do not have a common interface, what to do? It may help to realize that in these cases the design does not reflect reality well: practically, we created a marker interface solely to enable us to put a bunch of distinct objects into a common collection, but there is no semantical relationship between the objects.
So I believe in these cases the awkwardness of downcasts is a signal that there may be a deeper problem with our design.
You could implement a custom iterator that only iterates over the IRecievesBonus types.
Today I read a book and the author wrote that in a well-designed class the only way to access attributes is through one of that class methods. Is it a widely accepted thought? Why is it so important to encapsulate the attributes? What could be the consequences of not doing it? I read somewhere earlier that this improves security or something like that. Any example in PHP or Java would be very helpful.
Is it a widely accepted thought?
In the object-oriented world, yes.
Why is it so important to encapsulate the attributes? What could be the consequences of not doing it?
Objects are intended to be cohesive entities containing data and behavior that other objects can access in a controlled way through a public interface. If an class does not encapsulate its data and behavior, it no longer has control over the data being accessed and cannot fulfill its contracts with other objects implied by the public interface.
One of the big problems with this is that if a class has to change internally, the public interface shouldn't have to change. That way it doesn't break any code and other classes can continue using it as before.
Any example in PHP or Java would be very helpful.
Here's a Java example:
public class MyClass {
// Should not be < 0
public int importantValue;
...
public void setImportantValue(int newValue) {
if (newValue < 0) {
throw new IllegalArgumentException("value cannot be < 0");
}
}
...
}
The problem here is that because I haven't encapsulated importantValue by making it private rather than public, anyone can come along and circumvent the check I put in the setter to prevent the object from having an invalid state. importantValue should never be less than 0, but the lack of encapsulation makes it impossible to prevent it from being so.
What could be the consequences of not
doing it?
The whole idea behind encapsulation is that all knowledge of anything related to the class (other than its interface) is within the class itself. For example, allowing direct access to attributes puts the onus of making sure any assignments are valid on the code doing the assigning. If the definition of what's valid changes, you have to go through and audit everything using the class to make sure they conform. Encapsulating the rule in a "setter" method means you only have to change it in one place, and any caller trying anything funny can get an exception thrown at it in return. There are lots of other things you might want to do when an attribute changes, and a setter is the place to do it.
Whether or not allowing direct access for attributes that don't have any rules to bind them (e.g., anything that fits in an integer is okay) is good practice is debatable. I suppose that using getters and setters is a good idea for the sake of consistency, i.e., you always know that you can call setFoo() to alter the foo attribute without having to look up whether or not you can do it directly. They also allow you to future-proof your class so that if you have additional code to execute, the place to put it is already there.
Personally, I think having to use getters and setters is clumsy-looking. I'd much rather write x.foo = 34 than x.setFoo(34) and look forward to the day when some language comes up with the equivalent of database triggers for members that allow you to define code that fires before, after or instead of a assignments.
Opinions on how "good OOD" is achieved are dime a dozen, and also very experienced programmers and designers tend to disagree about design choices and philosophies. This could be a flame-war starter, if you ask people across a wide varieties of language background and paradigms.
And yes, in theory are theory and practice the same, so language choice shouldn't influence high level design very much. But in practice they do, and good and bad things happen because of that.
Let me add this:
It depends. Encapsulation (in a supporting language) gives you some control over how you classes are used, so you can tell people: this is the API, and you have to use this. In other languages (e.g. python) the difference between official API and informal (subject to change) interfaces is by naming convention only (after all, we're all consenting adults here)
Encapsulation is not a security feature.
Another thought to ponder
Encapsulation with accessors also provides much better maintainability in the future. In Feanor's answer above, it works great to enforce security checks (assuming your instvar is private), but it can have much further reaching benifits.
Consider the following scenario:
1) you complete your application, and distribute it to some set of users (internal, external, whatever).
2) BigCustomerA approaches your team and wants an audit trail added to the product.
If everyone is using the accessor methods in their code, this becomes almost trivial to implement. Something like so:
MyAPI Version 1.0
public class MyClass {
private int importantValue;
...
public void setImportantValue(int newValue) {
if (newValue < 0) {
throw new IllegalArgumentException("value cannot be < 0");
}
importantValue = newValue;
}
...
}
MyAPI V1.1 (now with audit trails)
public class MyClass {
private int importantValue;
...
public void setImportantValue(int newValue) {
if (newValue < 0) {
throw new IllegalArgumentException("value cannot be < 0");
}
this.addAuditTrail("importantValue", importantValue, newValue);
importantValue = newValue;
}
...
}
Existing users of the API make no changes to their code and the new feature (audit trail) is now available.
Without encapsulation using accessors your faced with a huge migration effort.
When coding for the first time, it will seem like a lot of work. Its much faster to type: class.varName = something vs class.setVarName(something); but if everyone took the easy way out, getting paid for BigCustomerA's feature request would be a huge effort.
In Object Oriente Programming there is a principle that is known as (http://en.wikipedia.org/wiki/Open/closed_principle):
POC --> Principle of Open and Closed. This principle stays for: a well class design should be opened for extensibility (inheritance) but closed for modification of internal members (encapsulation). It means that you could not be able to modify the state of an object without taking care about it.
So, new languages only modify internal variables (fields) through properties (getters and setters methods in C++ or Java). In C# properties compile to methods in MSIL.
C#:
int _myproperty = 0;
public int MyProperty
{
get { return _myproperty; }
set { if (_someVarieble = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; } }
}
C++/Java:
int _myproperty = 0;
public void setMyProperty(int value)
{
if (value = someConstantValue) { _myproperty = value; } else { _myproperty = _someOtherValue; }
}
public int getMyProperty()
{
return _myproperty;
}
Take theses ideas (from Head First C#):
Think about ways the fields can misused. What can go wrong if they're not set properly.
Is everything in your class public? Spend some time thinking about encapsulation.
What fields require processing or calculation? They are prime candidates.
Only make fields and methods public if you need to. If you don't have a reason to declare something public, don't.