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 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 someCollectionOfInts = GetSomeCollection();
IEnumerable 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.