I've been reading about the Liskov Substitution Principle (LSP) and I'm a little confused on how you adhere to it correctly. Especially when interfaces and subclasses are being used.
For example, if I have a base class:
public abstract class AccountBase
{
private string primaryAccountHolder;
public string PrimaryAccountHolder
{
get { return this.primaryAccountHolder; }
set
{
if (value == null) throw ArgumentNullException("value");
this.primaryAccountHolder = value;
}
}
public string SecondaryAccountHolder { get; set; }
protected AccountBase(string primary)
{
if (primary == null) throw new ArgumentNullException("primary");
this.primaryAccountHolder = primary;
}
}
Now let's say I have two accounts that inherit from the base class. One that REQUIRES the SecondaryAccountHolder. Adding a null guard to the sub-class is a violation of LSP, correct? So how would I design my classes in such a way that they don't violate LSP but one of my sub-classes requires a secondary account holder and one does not?
Compound the question with the fact that there could be tons of different types of accounts and they'll need to be generated through a factory or factory that returns a builder or something.
And I have the same question with interfaces. If I have an interface:
public interface IPrintsSomething
{
void PrintSomething(string text);
}
Wouldn't it be a violation of LSP to add a null guard clause for text on any class that implements IPrintsSomething? How do you protect your invariants? That is the correct word right? :p
You should research tell-don't-ask, and command/query separation, you could start here: https://pragprog.com/articles/tell-dont-ask
You should endeavor to tell objects what you want them to do; do not ask them questions about their state, make a decision, and then tell them what to do.
There's always something you want to do with the properties, well don't ask the object for them tell it to do something with them.
Instead of asking it and making decisions like this:
string holders = account.PrimaryAccountHolder;
if (accountHolder.SecondaryAccountHolder != null)
{
holders += " " + accountHolder.SecondaryAccountHolder;
}
Tell it:
string holders = account.ListAllHoldersAsAString();
Ideally, you'd actually tell it what you actually want to do with that string:
account.MailMergeAllAccountHoldersNames(letterDocument);
Now the logic for dealing with two account holders is in the subclass. Could be one, two or n account holders, the calling code doesn't care or need to know.
As for LSP, well if there's a formally (or informally) documented contract that says the clients must check for null on the second holder from the start then that's fine. It's not nice, but any null-pointer-exceptions will be the client's fault for not using the class correctly. (Note it's not true that adding a boolean property improves upon this, it's just maybe a little more readable, i.e. does anyone check IList.IsReadOnly before writing to it?!).
However, if you started with the double holder account and then added that condition that the second account holder can be null later for the single account, then you changed the contract, and an instance of the single could break existing code. If you're in full control of all places that use accounts, then you're allowed to do that, if that's a public api
you're changing, that's a different matter.
But tell-don't-ask avoids the whole problem in this case.
So how would I design my classes in such a way that they don't violate LSP but one of my sub-classes requires a secondary account holder and one does not?
The way out of this problem is by surfacing this variability to the contract of the base class. It may look like this (unnecessary implementation details left out):
public abstract class AccountBase
{
public string PrimaryAccountHolder
{
get { … }
set { … }
}
public string SecondaryAccountHolder
{
get { … }
set
{
…
if (RequiresSecondaryAccountHolder && value == null) throw …;
…
}
}
public abstract bool RequiresSecondaryAccountHolder { get; }
}
Then you are not violating the LSP, because the user of AccountBase can determine whether they have to or have not to provide the value of SecondaryAcccountHolder.
And I have the same question with interfaces. … Wouldn't it be a violation of LSP to add a null guard clause for text on any class that implements IPrintsSomething?
Make the validation an obvious part of the interface's contract. How? Document, that the implementor must chek the value of text for null.
Related
For the purposes of this question, a 'constant reference' is a reference to an object from which you cannot call methods that modify the object or modify it's properties.
I want something like this:
Const<User> user = provider.GetUser(); // Gets a constant reference to an "User" object
var name = user.GetName(); // Ok. Doesn't modify the object
user.SetName("New value"); // <- Error. Shouldn't be able to modify the object
Ideally, I would mark with a custom attribute (e.g. [Constant]) every method of a class that doesn't modify the instance, and only those methods can be called from the constant reference. Calls to other methods would result in an error, if possible, during compile time.
The idea is I can return a read-only reference to and be sure that it will not be modified by the client.
The technique you're referring to is called "const-correctness" which is a language feature of C++ and Swift, but not C#, unfortunately - however you're onto something by using a custom attribute because that way you can enforce it via a Roslyn extension - but that's a rabbit-hole.
Alternatively, there's a much simpler solution using interfaces: because C# (and I think the CLR too) does not support const-correctness (the closest we have is the readonly field modifier) the .NET base-class-library designers added "read-only interfaces" to common mutable types to allow a object (wheather mutable or immutable) to expose its functionality via an interface that only exposes immutable operations. Some examples include IReadOnlyList<T>, IReadOnlyCollection<T>, IReadOnlyDictionary<T> - while these are all enumerable types the technique is good for singular objects too.
This design has the advantage of working in any language that supports interfaces but not const-correctness.
For each type (class, struct, etc) in your project that needs to expose data without risk of being changed - or any immutable operations then create an immutable interface.
Modify your consuming code to use these interfaces instead of the concrete type.
Like so:
Supposing we have a mutable class User and a consuming service:
public class User
{
public String UserName { get; set; }
public Byte[] PasswordHash { get; set; }
public Byte[] PasswordSalt { get; set; }
public Boolean ValidatePassword(String inputPassword)
{
Hash[] inputHash = Crypto.GetHash( inputPassword, this.PasswordSalt );
return Crypto.CompareHashes( this.PasswordHash, inputHash );
}
public void ResetSalt()
{
this.PasswordSalt = Crypto.GetRandomBytes( 16 );
}
}
public static void DoReadOnlyStuffWithUser( User user )
{
...
}
public static void WriteStuffToUser( User user )
{
...
}
Then make an immutable interface:
public interface IReadOnlyUser
{
// Note that the interfaces' properties lack setters.
String UserName { get; }
IReadOnlyList<Byte> PasswordHash { get; }
IReadOnlyList<Byte> PasswordSalt { get; }
// ValidatePassword does not mutate state so it's exposed
Boolean ValidatePassword(String inputPassword);
// But ResetSalt is not exposed because it mutates instance state
}
Then modify your User class and consumers:
public class User : IReadOnlyUser
{
// (same as before, except need to expose IReadOnlyList<Byte> versions of array properties:
IReadOnlyList<Byte> IReadOnlyUser.PasswordHash => this.PasswordHash;
IReadOnlyList<Byte> IReadOnlyUser.PasswordSalt => this.PasswordSalt;
}
public static void DoReadOnlyStuffWithUser( IReadOnlyUser user )
{
...
}
// This method still uses `User` instead of `IReadOnlyUser` because it mutates the instance.
public static void WriteStuffToUser( User user )
{
...
}
So, these are the first two ideas I initially had, but don't quite solve the problem.
Using Dynamic Objects:
The first idea I had was creating a Dynamic Object that would intercept all member invokations and throw an error if the method being called isn't marked with a [Constant] custom attribute. This approach is problematic because a) We don't have the support of the compiler to check for errors in the code (i.e. method name typos) when dealing with dynamic objects, which might lead to a lot of runtime errors; and b) I intend to use this a lot, and searching for method names by name every time a method is called might have considerable performance impact.
Using RealProxy:
My second idea was using a RealProxy to wrap the real object and validate the methods being called, but this only works with objects that inherit from MarshalByRefObject.
In this example for the NYPizzaIngredientFactory, they can only make pizza with ThinCrustDough. How can i make a pizza that could use another factory's ingredients like ThickCrustDough from ChicagoPizzaIngredientFactory. I want to try stay away from builder and stick with abstract factory patterns and factory methods.
Your NYPizzaStore would have to use the ChicagoPizzaIngredientFactory if you want it to be able to use ThickCrustDough.
If you think about the practicality of this, however, it probably doesn't make sense to have them ship you the ingredients from Chicago.
In my mind, you have two options:
Have another factory located in NY that can produce thick dough (e.g. NYThickPizzaIngredientFactory). This is because your interface has a single createDough method that takes no arguments so you can't tell it what type of dough to make. It can only make one.
Alter your interface so that the createDough method accepts arguments that can tell the factory what type of dough to create. This is the one I would recommend.
The type of arguments can also be based on the particular factory. For instance:
//TDoughArts tells you what type of arguments the factory needs in order to make dough.
public interface IPizzaIngredientFactory<TDoughArgs> where TDoughArgs : IDoughArgs
{
//....
IDough CreateDough(TDoughArgs doughArgs);
//....
}
public interface IDoughArgs
{
}
public class NYPizzaDoughArgs : IDoughArgs
{
public enum DoughTypes
{
Thin = 0,
Thick = 1
}
public DoughTypes DoughType { get; set; }
}
public class NYPizzaIngredientFactory : IPizzaIngredientFactory<NYPizzaDoughArgs>
{
//....
public IDough CreateDough(NYPizzaDoughArgs doughArgs)
{
//Make the right dough based on args here
if(doughArgs.DoughType == DoughTypes.Thin)
//...
}
//....
}
I whipped this out in a few minutes so check for consistency, but I think you will get the idea.
You don't have to use generics. You can simply stick with the IDoughArgs interface if you don't want more specificity.
Usage:
var factory = new NYPizzaIngredientFactory();
var args = new NYPizzaDoughArgs();
args.DoughType = NYPizzaDoughArgs.DoughTypes.Thick;
var dough = factory.createDough(args);
The first problem I see is this:
public interface IDoughArgs
{
}
public class NYPizzaDoughArgs : IDoughArgs
{
public enum DoughTypes
{
Thin = 0,
Thick = 1
}
public DoughTypes DoughType { get; set; }
}
IDoughArgs has no members. The class that implements it, NYPizzaDoughArgs, has properties which are not implementations of IDoughArgs. That renders the IDoughArgs interface meaningless.
Additionally, look at this class declaration:
public class NYPizzaIngredientFactory : IPizzaIngredientFactory<NYPizzaDoughArgs>
What class is going to "know" the generic argument and know to create this class as opposed to some other generic implementation? It's going to get confusing when you get to that part. You'll need some sort of factory to create your factory.
Then, if you decide that ingredient factories vary by more than just the type of dough, and you need more generic arguments, it's going to get really messy.
And, what happens if, in addition to having options such as thickness that are specific to just one dough type, you need options that are specific to just one thickness? Perhaps thick dough is only an option if you've selected New York or Chicago style (not European) and stuffed crust is only an option if you've selected a thick crust. That's going to get really difficult to describe with interfaces. It sounds more like data.
Here's a stab at another way to implement this:
public enum PizzaStyle
{
NewYork = 1,
Chicago = 2,
Greek = 4
}
public enum CrustType
{
Thick = 1024,
Thin = 2048,
HandTossed = 4096
}
public enum CrustOption
{
Stuffed = 32768
}
public enum PizzaDoughOption
{
NewYorkThin = PizzaStyle.NewYork + CrustType.Thin,
NewYorkHandTossed = PizzaStyle.NewYork + CrustType.HandTossed,
NewYorkThick = PizzaStyle.NewYork + CrustType.Thick,
NewYorkThickStuffed = NewYorkThick + CrustOption.Stuffed,
ChicagoThin = PizzaStyle.Chicago + CrustType.Thin,
ChicagoHandTossed = PizzaStyle.Chicago + CrustType.HandTossed,
ChicagoThick = PizzaStyle.Chicago + CrustType.Thick,
ChicagoThickStuffed = ChicagoThick + CrustOption.Stuffed,
Greek = PizzaStyle.Greek // only comes one way?
}
There are other ways to represent this same data. Even if there were fifty values in the PizzaDoughOption enumeration, it's probably still easier that way, building a definitive, readable list of valid options, as opposed to trying to represent that in code with a bunch of branches. (If you want to unit test that, you'll end up coding every single combination anyway in unit tests.)
And there are several ways you could use this data. You could present just a big list of options. You could allow users to select from the various options and, as you go, determine whether it matches a valid combination. Or they could select any option and you could narrow the list of options according to which include the desired option. (You want a stuffed crust? Ok, that's either New York thick crust or Chicago thick crust.)
Now, if you need a factory to create dough according to type, you could do this:
public interface IDoughFactory
{
Dough GetDough(PizzaDoughOption doughOption);
}
The implementation might look something like this. To be honest I might use a "factory factory" here, but for now since there are only three types I'll keep it simpler.
public class DoughFactory : IDoughFactory
{
// Each of these also implement IDoughFactory
private readonly NewYorkDoughFactory _newYorkDoughFactory;
private readonly ChicagoDoughFactory _chicagoDoughFactory;
private readonly GreekDoughFactory _greekDoughFactory;
public DoughFactory(
NewYorkDoughFactory newYorkDoughFactory,
ChicagoDoughFactory chicagoDoughFactory,
GreekDoughFactory greekDoughFactory)
{
_newYorkDoughFactory = newYorkDoughFactory;
_chicagoDoughFactory = chicagoDoughFactory;
_greekDoughFactory = greekDoughFactory;
}
public Dough GetDough(PizzaDoughOption doughOption)
{
if (MatchesPizzaStyle(doughOption, PizzaStyle.NewYork))
return _newYorkDoughFactory.GetDough(doughOption);
if (MatchesPizzaStyle(doughOption, PizzaStyle.Chicago))
return _chicagoDoughFactory.GetDough(doughOption);
if (MatchesPizzaStyle(doughOption, PizzaStyle.Greek))
return _greekDoughFactory.GetDough(doughOption);
// Throw an exception or return a default dough type. I'd throw the exception.
}
private bool MatchesPizzaStyle(PizzaDoughOption doughOption, PizzaStyle pizzaStyle)
{
return ((int) doughOptions & (int) pizzaStyle) == (int) pizzaStyle;
}
}
Now your more concrete dough factories (New York, Chicago, Greek) all receive the same PizzaDoughOption. If they care whether thin or thick has been selected, they can handle it. If that option doesn't exist they can ignore it. Even if something has gone wrong in an outer class and somehow someone has invoked GreekDoughFactory with the StuffedCrust option, it won't fail. It just ignores it.
What would be the possible point to all of this?
First, the class creating a pizza has no knowledge of the intricacies of creating the right dough type. It just depends on a dough factory, passes a parameter, and gets the right dough. That's simple and testable.
Second, you don't have to call new anywhere. You can employ dependency injection all the way down. That way the class that depends on the abstract IDoughFactory doesn't know anything about what dependencies DoughFactory has.
Likewise, maybe the concrete dough factories have dependencies of their own and they differ significantly from one to the next. As long as those are getting resolved from the container and injected into DoughFactory, that's fine, and DoughFactory won't know anything about their dependencies.
All of the dependencies are wired up in your DI container, but the classes themselves are small, simple, and testable, depending on abstractions and not coupled to implementations of anything.
Someone might look and this and think it's a little more complicated. What's critical is that not only does it keep individual classes decoupled, but it leaves a path forward for future change. The design of your classes, which shouldn't have to change too much, won't closely mirror the details of specific types of pizzas, which can and should change. You don't want to have to re-architect your pizza application because of a new kind of pizza.
I'm very aware of type checking, but have found myself in a unique situation and I'm beginning to question whether I'm within best practices. Hopefully the veteran comments will give me some direction and things worth thinking more deeply about. And, to be honest, it's not that what I have will not work, but as I'm making some other changes I'm wondering what the pitfalls might be and whether I should change tactics. There doesn't seem to be a lot out there (in fact I havent' seen anything as basic type checking takes the majority of the search results).
I have a situation where I'm developing a bill of material interface system. In this system, the following class diagram applies:
This is generically speaking, but the point here is that there are only three concrete types worth concerning. Because it's easy to set property values in the constructors of the objects, I had defined (generically speaking again of course) the IMaterial interface as so:
public interface IMaterial
{
bool IsCommodity { get; }
bool IsAssembly { get; }
bool IsUnclassified { get; }
...
}
Originally, the thought was that the object graph has very little room to change, performance is improved through a preset boolean value, and I don't have to worry about breaking various other principles by type checking concrete types.
So for example, I can do this...
bool hasCommodities = materialCollection.Any(item => item.IsCommodity);
bool hasAssemblies = materialCollection.Any(item => item.IsAssembly);
bool hasDescriptionOnly = materialCollection.Any(item => item.IsUnclassified);
or this...
if (bomMaterial.IsAssembly)
{
symbol = new BomAssemblySymbol();
}
else
{
symbol = new BomItemSymbol();
}
instead of this...
bool hasCommodities = materialCollection.Any(item => item is ClassifiedItem);
bool hasAssemblies = materialCollection.Any(item => item is Assembly);
bool hasDescriptionOnly = materialCollection.Any(item => item is UnclassifiedItem);
or this...
if (bomMaterial is Assembly)
{
symbol = new BomAssemblySymbol();
}
else
{
symbol = new BomItemSymbol();
}
So in my case, the interface's use of properties means less dependency on concrete types in the implementation detail. But then again, it begs the question, what if another type does come along? What's the best answer here? And is there a pattern that maybe I'm overlooking and should be considering for this? And if anyone is wondering why the consuming code cares, it's because with the CAD system, there is a single command the user interacts with that in turn leverages these objects. I can't create separate commands for them just because of the single line of code difference.
Update
Here's a more complete example showing how the CAD-side seems to bottle neck processes. The TryGetMaterialInformation() method prompts the user in the CAD system for specific input. The SymbolUtility.InsertSymbol() method just wraps a common set of user prompts for inserting any symbol and then inserts it.
public override void Execute()
{
IMaterial bomMaterial = null;
bool multipleByReference = false;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
if (!TryGetMaterialInformation(out bomMaterial, out multipleByReference))
{
ed.WriteMessage("\nExiting command.\n");
return;
}
IBlockSymbol symbol;
if (bomMaterial.IsAssembly)
{
symbol = new BomAssemblySymbol();
}
else
{
symbol = new BomItemSymbol();
}
if (multipleByReference)
{
SymbolUtility.InsertMultipleByReferenceSymbol(symbol, bomMaterial);
}
else
{
SymbolUtility.InsertSymbol(symbol, bomMaterial);
}
}
From SymbolUtility
internal static void InsertSymbol(IBlockSymbol symbol, IMaterial material)
{
ICADDocumentDTO document = new CADDocumentDTO();
Editor ed = document.ActiveDocument.Editor;
//Get the insert point
Point3d insertPoint = Point3d.Origin;
if (!CommandUtility.TryGetPoint("Select insert point: ", out insertPoint))
{
ed.WriteMessage("\nExiting command.\n");
return;
}
//Insert the object
using (ISystemDocumentLock documentLock = document.Lock())
{
CreateSymbolDefinition(symbol, document);
symbol.Insert(insertPoint, material, document);
}
}
If you have properties like IsCommodity, IsAssembly, and IsClassified, they should describe some sort of logical property that can be ascribed to an instance. They should not tell the consumer what the concrete type is.
The reason is that a consumer of IMaterial should neither know nor need to know about any concrete type that implements IMaterial.
If those properties actually indicate the concrete types, then all those properties accomplish is type checking, and they will lead to casting objects back to their concrete types, which defeats the purpose of creating an abstraction (interface.)
It looks that way to me since you're considering the properties as a direct alternative to type checking.
The alternative is that instead of the consumer looking at the class properties and deciding what to do or not to with the class, the consumer just tells the class what do to (calling a method) and the implementation of the class itself determines how to carry that out.
So, my basic set up is like so: I have items, which are restricted to different classes. These items have effects, which are also restricted to different classes. For example, I might have an item that may only be wielded by elves, while another item might be wielded by everyone, but gives specific bonuses/effects to elves.
Here's a Restriction class:
public class Restriction {
private int _base_id = 0;
private bool _qualify = true;
public Restriction() { }
// ... Base_ID and Qualify getters and setters here
public virtual bool Check(int c) {
if(_qualify) { return c == _base_id; }
else { return c != _base_id; }
}
A child of the Restriction class might be RaceRestriction, which only overrides the constructor:
public RaceRestriction(reference.races r, bool qual) {
Base_ID = (int)r; Qualify = qual;
}
reference.races r is an enum in a reference file. The idea here is that I can extend this "Restriction" syntax to any class that I define in the reference file -- so I can make Restrictions on race, class, stats, whatever I need.
So, this all culminates later, when I define (for example) an item, which has restrictions on who can equip it.
Below is a snippet from the Equipment class, where I define a piece of equipment for later use (hopefully it's readable as is):
public Equipment() {
...
_master_equipment_list[1] = new Equipment {
Name = "Sword",
Description = "It's just a sword for demonstration",
Stats = {
new Attribute {
Stat_Modifier = new KeyValuePair<reference.stats, int>(reference.stats.ATTACK, 5),
Restrictions = {
new RaceRestriction(reference.races.TROLL, false)
}
}
},
Restrictions = {
new ClassRestriction(reference.class.WARRIOR, true)
}
}
So the idea behind this is that using this system, I've defined a sword that can only be used by warriors (base warrior true restriction on the item), and it gives 5 attack to any trolls wielding it.
What I've cornered myself into is that this will only work for either logical AND or logical OR strings of thought. Say my item says "warriors can use this" and it says "elves can use this." Do I really mean "warriors or elves" or do I mean "warrior elves?"
That distinction, I think, is going to be necessary -- so I need to attach some logic to each restriction and make, essentially, I think, sets of restrictions that are tied to one another, that string with other sets of restrictions, etc., but I feel like that will get out of hand very fast.
Is there a better way I can do this?
Rather than defining specific restriction classes, I would design this by defining an interface called IRestrictable to be implemented by the Equipment classes. This interface would contain at least one method called CheckEligibility (or similar) which would return a bool. Your equipment class would then be free to use whatever logic expression it liked to come up with the answer, based on whatever inputs you wanted and whatever information the class had available at the time. You could have several methods on the interface if you need to check restrictions under different circumstances. You would be free to implement specific classes deriving from Equipment for specific types of equipment that had complicated rules.
One of the most important aspects of OOP is data hiding. Can somebody explain using a simple piece of code what data hiding is exactly and why we need it?
Data or Information Hiding is a design principal proposed by David Paranas.
It says that you should hide the
design decisions in one part of the
program that are likely to be changed
from other parts of the program, there
by protecting the other parts from
being affected by the changes in the
first part.
Encapsulation is programming language feature which enables data hiding.
However note that you can do data\information hiding even without encapsulation. For example using modules or functions in non Object Oriented programming languages. Thus encapsulation is not data hiding but only a means of achieving it.
While doing encapsulation if you ignore the underlying principal then you will not have a good design. For example consider this class -
public class ActionHistory
{
private string[] _actionHistory;
public string[] HistoryItems
{
get{return _actionHistory; }
set{ _actionHistory = value; }
}
}
This calls encapsulates an array. But it does not hide the design decision of using a string[] as an internal storage. If we want to change the internal storage later on it will affect the code using this class as well.
Better design would be -
public class ActionHistory
{
private string[] _actionHistory;
public IEnumerable<string> HistoryItems
{
get{return _actionHistory; }
}
}
I'm guessing by data hiding you mean something like encapsulation or having a variable within an object and only exposing it by get and modify methods, usually when you want to enforce some logic to do with setting a value?
public class Customer
{
private decimal _accountBalance;
public decimal GetBalance()
{
return _accountBalance;
}
public void AddCharge(decimal charge)
{
_accountBalance += charge;
if (_accountBalance < 0)
{
throw new ArgumentException(
"The charge cannot put the customer in credit");
}
}
}
I.e. in this example, I'm allowing the consuming class to get the balance of the Customer, but I'm not allowing them to set it directly. However I've exposed a method that allows me to modify the _accountBalance within the class instance by adding to it via a charge in an AddCharge method.
Here's an article you may find useful.
Information hiding (or more accurately encapsulation) is the practice of restricting direct access to your information on a class. We use getters/setters or more advanced constructs in C# called properties.
This lets us govern how the data is accessed, so we can sanitize inputs and format outputs later if it's required.
The idea is on any public interface, we cannot trust the calling body to do the right thing, so if you make sure it can ONLY do the right thing, you'll have less problems.
Example:
public class InformationHiding
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
/// This example ensures you can't have a negative age
/// as this would probably mess up logic somewhere in
/// this class.
private int _age;
public int Age
{
get { return _age; }
set { if (value < 0) { _age = 0; } else { _age = value; } }
}
}
Imagine that the users of your class are trying to come up with ways to make your class no longer fulfill its contract. For instance, your Banking object may have a contract that ensures that all Transactions are recorded in a log. Suppose mutation of the Bank's TransactionLog were publically accessible; now a consuming class could initiate suspect transactions and modify the log to remove the records.
This is an extreme example, but the basic principles remain the same. It's up to the class author to maintain the contractual obligations of the class and this means you either need to have weak contractual obligations (reducing the usefulness of your class) or you need to be very careful about how your state can be mutated.
What is data hiding?
Here's an example:
public class Vehicle
{
private bool isEngineStarted;
private void StartEngine()
{
// Code here.
this.isEngineStarted = true;
}
public void GoToLocation(Location location)
{
if (!this.isEngineStarted)
{
this.StartEngine();
}
// Code here: move to a new location.
}
}
As you see, the isEngineStarted field is private, ie. accessible from the class itself. In fact, when calling an object of type Vehicle, we do need to move the vehicle to a location, but don't need to know how this will be done. For example, it doesn't matter, for the caller object, if the engine is started or not: if it's not, it's to the Vehicle object to start it before moving to a location.
Why do we need this?
Mostly to make the code easier to read and to use. Classes may have dozens or hundreds of fields and properties that are used only by them. Exposing all those fields and properties to the outside world will be confusing.
Another reason is that it is easier to control a state of a private field/property. For example, in the sample code above, imagine StartEngine is performing some tasks, then assigning true to this.isEngineStarted. If isEngineStarted is public, another class would be able to set it to true, without performing tasks made by StartEngine. In this case, the value of isEngineStarted will be unreliable.
Data Hiding is defined as hiding a base class method in a derived class by naming the new class method the same name as the base class method.
class Person
{
public string AnswerGreeting()
{
return "Hi, I'm doing well. And you?";
}
}
class Employee : Person
{
new public string AnswerGreeting()
{
"Hi, and welcome to our resort.";
}
}
In this c# code, the new keyword prevents the compiler from giving a warning that the base class implementation of AnswerGreeting is being hidden by the implementation of a method with the same name in the derived class. Also known as "data hiding by inheritance".
By data hiding you are presumably referring to encapsulation. Encapsulation is defined by wikipedia as follows:
Encapsulation conceals the functional
details of a class from objects that
send messages to it.
To explain a bit further, when you design a class you can design public and private members. The class exposes its public members to other code in the program, but only the code written in the class can access the private members.
In this way a class exposes a public interface but can hide the implementation of that interface, which can include hiding how the data that the class holds is implemented.
Here is an example of a simple mathematical angle class that exposes values for both degrees and radians, but the actual storage format of the data is hidden and can be changed in the future without breaking the rest of the program.
public class Angle
{
private double _angleInDegrees;
public double Degrees
{
get
{
return _angleInDegrees;
}
set
{
_angleInDegrees = value;
}
}
public double Radians
{
get
{
return _angleInDegrees * PI / 180;
}
set
{
_angleInDegrees = value * 180 / PI;
}
}
}