hiding property from derived class - c#

Jon Skeet brought up this issue once in his videos
(though didn't provide with an answer).
Let's say we have a Class named Person
and the Person class has Name property
Then we have another class, Spy.
Of course a Spy is a Person so we will derive from the Person class.
public class Person
{
public string Name { get; set; }
}
public class Spy : Person
{
}
We don't want people to know the Spy's name so we'd want this to give a compilation error:
static void ReportSpy(Spy spy) {
string name = spy.Name;
}
or either:
static void ReportSpy(Spy spy)
{
Person spyAsPerson = spy;
string name = spyAsPerson.Name;
}
How could we prevent this kind of things from happening?

Make the Name property virtual in the base Person class. In derived Spy class, override the property and throw Exception in getter.
public class Person
{
public virtual string Name { get; set; }
}
public class Spy : Person
{
public override string Name
{
get
{
throw new Exception("You never ask for a spy's name!");
}
set
{
base.Name = value;
}
}
}
But, rather than throwing exception, I'd suggest something like
get
{
return "**********";
}
Because, it breaks LSP (mentioned in another answer). What that means here (just an example) is, I can always do like
Person x = new Spy();
and pass it to some other method, which might be like
void RegisterForNextBallGame(Person p)
{
playerList.Add(p.Name);
}
This method being unaware of the some spy roaming around the stadium, crashes while doing a simple honest duty!
Edit
Just to make it clear, this name=********** is still not a right solution. It will just save from the exceptions! Later, one might find lot of Persons walking down the code with name ********** which will cause later surprises and other issues.
A better solution would be a better design. Check Nathan's answer to get some hint.

If part of being a person is disclosing your name: Spy's aren't people
Having Spy inherit from person breaks the Liskov substitution principle: An object may be replaced with its subtype.
If Spys don't disclose their name they shouldn't be People in the context of your design. Perhaps you could design it differently:
public interface IPerson
{
void EatLunch();
}
public interface INameDisclosingPerson : IPerson
{
string Name {get; set; }
}
public interface ISpy : IPerson
{
void DrinkCocktail();
Package MakeDrop();
}
An example of this poor design in the real world is NetworkStream. It implements the Position property by throwing a NotSupportedException. So code you write for a Stream may break at runtime for the NetworkStream. I'm also not a fan of this. A piece of design guidance: wrong things should break at compilation time and objects that inherit from interfaces they can't implement are terrible.

You can't. As already mentioned you could throw an Exception when accessing Spy's Name property but this would still compile. And, also already mentioned, this would break Liskov substitution principle and, I'd like to add, the open-closed principle as well.

You can hide base class method or property with new keyword:
public class Person
{
public string Name { get; set; }
}
public class Spy : Person
{
public new string Name
{
get { throw new InvalidOperationException(); }
}
}
It will not give you compilation errors, and you will still be able to access the base class Name property if you cast.
If you can modify the base class, change the property to virtual. Then you can override it in the derived and class and throw exception even with polymorphic calls.
All this will work at runtime, nothing you can do about it at compile time.
And as others mentioned in their answers, such design breaks Liskov substitution principle and should be avoided.

Related

At what point are extension methods on POCO classes overkill?

My POCO's structure basically goes like this:
Person which has: Addresses, Phones, CaseNotes, NoticeOfActions.
I started writting a PersonExtension class which I found quite useful with, say, the following example method:
public static Person GetPersonsPhones(this Person person, string userID)
{
using (var context = ConnectDataContext.Create())
{
var pPhones =
context.tblPhones.Where(phones => phones.PersonID == person.PersonID).Select(
phones =>
new Phone()
{
PhoneID = phones.PhoneID,
PhoneType =
new PhoneType
{
PhoneTypeID = phones.tblAdminPhoneType.PhoneTypeID,
TypeDescription = phones.tblAdminPhoneType.PhoneTypeDesc
},
PhoneNumber = phones.PhoneNumber,
Extension = phones.Extension
});
person.Phones = pPhones.ToList<Phone>();
return person;
}
}
Now I have similar Extension Methods for Person that get the Address Collection. What I am wondering is if there is a point where this is detrimental. Due to the nature of my environment almost everything fits under Person in the has-a way.
Is that okay or is there something bad that I will run into from that? Am I incurring WAY more overhead that way?
The alternative seems to be to simply pass the Person.ID since that is what I need to get the Phones from the DB and then add it to my Person object but that seems, to me anyway, to be the same thing.
I think there is a communication breakdown here which is most likely my fault as I don't always use the right words for things.
In my DB there is tblPerson and tblPhone. I have a class called Person and a class called Phone. My Person class has a Property of IList<Phone>Phones.
The Extension Methods in question are for CRUD methods for the child properties of my Base Class.
i.e. Person.GetPhones() fills the IList<Phone>Phones Property of that Person object. Person.SavePhones() would Save any changes to the Phones to the DB for that Person object.
I am not arguing that what I am doing is RIGHT(I doubt it is...:() just trying to make sure everyone understands what I am asking.
Also, I am using LinqToSQL for the DB access.
Your person here should be a fully fledged domain object, not a POCO. The person should tell some thing their phone numbers, the person should not be responsible for going off to the database and fetching them out! The later applies whether you choose an extension method or not.
Regarding your question however, I see extension methods as way of extending some functionality of third party code. For example, you can do ToUpper() on strings. It would be nice to extend this to do Title Case. Here we are extending the behavior. We are "adding" to third party code without having the source at hand, because the alternative would be to introduce a new object that wrapped string to do so. Extension methods here then are only really syntactic sugar.
If you own the code, then extension methods are pointless because you can just make the method a fully fledge method on the class in question. The reason I say this is that with a proper method you can access private fields of the class you are extending, therefore using an extenstion method you are limited to public visibility, just like a normal static method.
I think the main downside would tend to be code organization. Isn't the point of OOP to try and keep related code together?
I'm curious why you are using an extension method here. If Person is an entity object, I would create a partial class that extends the entity class. Seems to be a bit better organization here to me.
If you are using POCO classes with EntityFramework code-first model, you should be able to write your POCO class like this (including only the Phones for now, just to demonstrate):
class Person
{
public long Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Phone> Phones { get; set; }
}
class Phone
{
public long Id { get; set; }
public string Name { get; set; }
public long PersonId { get; set; }
public virtual Person Person { get; set; }
}
Now you can access myPerson.Phones directly and there is no need for your extension method.
If it's your class then you should write real methods for the class. Extension methods are useful for adding functionality to classes that you can't change, for example, a class from a library you don't have the source for and that you can't just derive from.

Object-Oriented Programming

I am new to C#. I have a Persons class with this function:
public virtual void InputPerson(Persons P)
{
P.ID = int.Parse(Console.ReadLine());
Console.WriteLine("Titel:");
P.Titel = Console.ReadLine();
Console.WriteLine("Name:");
P.Name = Console.ReadLine();
Console.WriteLine("Surname:");
P.Surname = Console.ReadLine();
}
And I have a User class that inherits form this Persons class. I now need to create a InputUser function in the User class that makes use of this InputPerson function in the Persons class without rewriting all the code from the InputPerson function to the InputUser function. Here is my code from the InputUser function:
public override void InputPerson(User U)
{
Console.WriteLine("Please enter a Customer:");
Console.WriteLine("Customer ID:");
base.InputPerson;
Console.WriteLine("Telephone Number:");
U.Telephone = int.Parse(Console.ReadLine());
Console.WriteLine();
}
This InputUser code gives me a error stating:
'UserCustomerNotes.User.InputPerson(UserCustomerNotes.User)': no suitable method found to override
Can anyone please help?
Thanks in advance
base.InputPerson; cannot work at all.
You cannot override void InputPerson(Persons P) with void InputPerson(User U) as you seem to imply. The signatures must be identical.
This is just me taking more tangential look at this question but under the traditional guidelines for OO design a user is a person therefore you get inheritance. However, when we look at SOLID principles and especially the "Liskov Substitution Principle":
"Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it." — Robert Martin, LSP paper linked from The Principles of OOD
What does that mean? Well, we should be able to substitute an instance of a subclass for its parent class and everything should continue to work. In this case it won't work, there are extra properties that you are depending on for User that a Person does not have.
In this case have you considered doing composition rather than inheritance?
public class Person
{
public static void InputPerson(Person p)
{
// Do the input logic here
}
}
public class User
{
public Person Person { get; private set; }
public static void InputUser(User u)
{
if (u.Person == null)
u.Person = new Person;
Person.InputPerson(u.Person);
Console.WriteLine("Telephone:");
u.Telephone = Console.ReadLine();
}
}
We could go further into SOLID and take a look at the Single Responsibility Principle and ask is the Person/User object handles the logic of being a person but should it know about creating that object from the console? What happens if you want to re-use the same logic for a windows application or a WPF application?
To override a method you must keep its signature, which you dont(you change the type of the parameter from Persons to User, so you create a new method). So remove the 'override' keyword.
Also, use:
InputPerson(U);
Instead of:
base.InputPerson;
You could also do the following, taking advantage of the class inheritance:
public override void InputPerson(Persons P)
{
// Code in here
}
Because a User is a Persons, then you are allowed to directly pass it into the Method as a parameter. If however there are
custom Properties on a User that are not present on a Persons you could introduce generics.
public class Persons<T>
{
public virtual void InputPerson(T p)
{
// code here.
}
}
public class User : Person<User>
{
public override void InputPerson(User p)
{
// code here. You can now treat the input as a user
// as you have told your base class that the 'T' is a user.
}
}
Instead of overriding the method, use the new keyword instead as the signatures are different.
public new void InputPerson(User U)
Then all you need to do is pass User U through to the base class, so instead of
base.InputPerson;
use
base.InputPerson(U);

How to hide an inherited property in a class without modifying the inherited class (base class)?

If i have the following code example:
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA : ClassBase
{
public int JustNumber { get; set; }
public ClassA()
{
this.ID = 0;
this.Name = string.Empty;
this.JustNumber = string.Empty;
}
}
What should I do to hide the property Name (Don't shown as a member of ClassA members) without modifying ClassBase ?
I smell a code smell here. It is my opinion that you should only inherit a base class if you're implementing all of the functionality of that base class. What you're doing doesn't really represent object oriented principles properly. Thus, if you want to inherit from your base, you should be implementing Name, otherwise you've got your inheritance the wrong way around. Your class A should be your base class and your current base class should inherit from A if that's what you want, not the other way around.
However, not to stray too far from the direct question. If you did want to flout "the rules" and want to continue on the path you've chosen - here's how you can go about it:
The convention is to implement the property but throw a NotImplementedException when that property is called - although, I don't like that either. But that's my personal opinion and it doesn't change the fact that this convention still stands.
If you're attempting to obsolete the property (and it's declared in the base class as virtual), then you could either use the Obsolete attribute on it:
[Obsolete("This property has been deprecated and should no longer be used.", true)]
public override string Name
{
get
{
return base.Name;
}
set
{
base.Name = value;
}
}
(Edit: As Brian pointed out in the comments, the second parameter of the attribute will cause a compiler error if someone references the Name property, thus they won't be able to use it even though you've implemented it in derived class.)
Or as I mentioned use NotImplementedException:
public override string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
However, if the property isn't declared as virtual, then you can use the new keyword to replace it:
public new string Name
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
You can still use the Obsolete attribute in the same manner as if the method was overridden, or you can throw the NotImplementedException, whichever you choose. I would probably use:
[Obsolete("Don't use this", true)]
public override string Name { get; set; }
or:
[Obsolete("Don't use this", true)]
public new string Name { get; set; }
Depending on whether or not it was declared as virtual in the base class.
While technically the property won't be hidden, one way to strongly discourage its use is to put attributes on it like these:
[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
This is what System.Windows.Forms does for controls that have properties that don't fit. The Text property, for instance, is on Control, but it doesn't make sense on every class that inherits from Control. So in MonthCalendar, for instance, the Text property appears like this (per the online reference source):
[Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
Bindable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
get { return base.Text; }
set { base.Text = value; }
}
Browsable - whether the member shows up in the Properties window
EditorBrowsable - whether the member shows up in the Intellisense dropdown
EditorBrowsable(false) won't prevent you from typing the property, and if you use the property, your project will still compile. But since the property doesn't appear in Intellisense, it won't be as obvious that you can use it.
Just hide it
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA : ClassBase
{
public int JustNumber { get; set; }
private new string Name { get { return base.Name; } set { base.Name = value; } }
public ClassA()
{
this.ID = 0;
this.Name = string.Empty;
this.JustNumber = 0;
}
}
Note: Name will still be a public member of ClassBase, given the constraint of not changing the base class there is no way to stop that.
Why force inheritance when it's not necessary?
I think the proper way of doing it is by doing has-a instead of a is-a.
public class ClassBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class ClassA
{
private ClassBase _base;
public int ID { get { return this._base.ID; } }
public string JustNumber { get; set; }
public ClassA()
{
this._base = new ClassBase();
this._base.ID = 0;
this._base.Name = string.Empty;
this.JustNumber = string.Empty;
}
}
I don’t think a lot of the people replying here understand inheritance at all. There is a need to inherit from a base class and hide its once public var’s and functions. Example, lets say you have a basic engine and you want to make a new engine that is supercharged. Well, 99% of the engine you will use but you will tweak a bit of its functionality to make it run much better and yet still there is some functionality that should only be shown to the modifications made, not the end user. Because we all know that every class MS puts out doesn’t really ever need any modifications.
Besides using the new to simply override the functionality it is one of the things that Microsoft in their infinite wis….. oh, I mean mistakes considered a tool not worthwhile anymore.
The best way to accomplish this now is multi-level inheritance.
public class classA
{
}
public class B : A
{}
public class C : B
{}
Class B does all your work and class C exposes what you need exposed.
You can't, that's the whole point of inheritance: the subclass must offer all methods and properties of the base class.
You could change the implementation to throw an exception when the property is called (if it were virtual)...
I completely agree that properties should not be removed from base classes, but sometimes a derived class might have a different more appropriate way to enter the values. In my case, for example, I am inheriting from ItemsControl. As we all know, ItemsControl has the ItemsSource property, but I want my control to merge data from 2 sources (for example, Person and Location). If I were to have the user enter the data using ItemsSource, I would need to separate and then recombine the values, so I created 2 properties to enter the data. But back to the original question, this leaves the ItemsSource, which I do not want the user to use because I am "replacing" it with my own properties. I like the Browsable and EditorBrowsable ideas, but it still does not prevent the user from using it. The basic point here is that inheritance should keep MOST of the properties, but when there is a large complex class (especially ones where you cannot modify the original code), rewriting everything would be very inefficient.
You can use Browsable(false)
[Browsable( false )]
public override string Name
{
get { return base.Name; }
set { base.Name= value; }
}
I think it is bad design if you have to do this, especially if you are able to design the code from the ground up.
Why?
Good design is to let the base-class share common properties that a certain concept has (virtual or real). Example: System.IO.Stream in C#.
Further down the lane bad design will increase the cost for maintenance and make implementation harder and harder. Avoid this as much as possible!
Basic rules which I use:
Minimize the number of properties and methods in the base-class. If you do not expect to use some properties or methods in a class that inherits the base class; do not put it in the baseclass then. If you are in the developmentstage of a project; always go back to the drawing-board now an then to check the design because things change! Redesign when needed. When your project is live the costs for changing things later in the design will go up!
If you are using a baseclass implemented by a 3:rd party, consider "go up" one level instead of "overriding" with "NotImplementedException" or such. If there is no other level, consider design the code from scratch.
Always consider to seal classes you do not want anyone to be able to inherit it. It forces coders to "go up one level" in the "inheritance- hierarchy" and thus "loose ends" like "NotImplementedException" can be avoided.
I know that the question is old, but what you can do is override the PostFilterProperties like this:
protected override void PostFilterProperties(System.Collections.IDictionary properties)
{
properties.Remove("AccessibleDescription");
properties.Remove("AccessibleName");
properties.Remove("AccessibleRole");
properties.Remove("BackgroundImage");
properties.Remove("BackgroundImageLayout");
properties.Remove("BorderStyle");
properties.Remove("Cursor");
properties.Remove("RightToLeft");
properties.Remove("UseWaitCursor");
properties.Remove("AllowDrop");
properties.Remove("AutoValidate");
properties.Remove("ContextMenuStrip");
properties.Remove("Enabled");
properties.Remove("ImeMode");
//properties.Remove("TabIndex"); // Don't remove this one or the designer will break
properties.Remove("TabStop");
//properties.Remove("Visible");
properties.Remove("ApplicationSettings");
properties.Remove("DataBindings");
properties.Remove("Tag");
properties.Remove("GenerateMember");
properties.Remove("Locked");
//properties.Remove("Modifiers");
properties.Remove("CausesValidation");
properties.Remove("Anchor");
properties.Remove("AutoSize");
properties.Remove("AutoSizeMode");
//properties.Remove("Location");
properties.Remove("Dock");
properties.Remove("Margin");
properties.Remove("MaximumSize");
properties.Remove("MinimumSize");
properties.Remove("Padding");
//properties.Remove("Size");
properties.Remove("DockPadding");
properties.Remove("AutoScrollMargin");
properties.Remove("AutoScrollMinSize");
properties.Remove("AutoScroll");
properties.Remove("ForeColor");
//properties.Remove("BackColor");
properties.Remove("Text");
//properties.Remove("Font");
}

.NET inheritance: suppress a property from the base class

Consider the Employee, Manager, and Assistant classes:
public class Emp
{
public string Name { get; set; }
public Manager Manager { get; set; }
public Assistant Assistant { get; set; }
}
public class Manager : Emp
{
}
public class Assistant : Emp
{
}
The goal is to DISALLOW a piece of code to access a property like this:
var foo = new Manager();
var elmo = new Emp();
elmo.Manager = foo;
elmo.Manager.Manager = new Manager();
//how to disallow access to Manager.Manager ?
Because Manager inherits from Emp, it has a .Manager and .Assistant property.
Question
Are there any modifiers in .NET's inheritance implementation to remove the .Manager and .Assistant properties?
Update
Thank you for your great answers, everyone. I was hoping the simplification and contrivance of Emp/Mgr would show through in this question. It's clear that the inheritance, in this example, should be taken to another commonality (something like Person, where the classes would share names, birthdates, etc.) Your input is much appreciated!
Doing this would violate the Liskov substitution principle, and is usually a sign of a questionable design. In general, any subclass should be able to be used in any context that a base class would be. If Managers don't have .Managers, then they aren't Emps, and shouldn't inherit from them.
No - because it would break Liskov's Subsitution Principle. Basically, you can add things, but you can't take them away.
You could potentially override the property to throw an exception at execution time, but you can't do it at compile time.
Generally if you want to disallow this sort of thing, you should consider composition rather than inheritance, as you don't have a genuine inheritance relationship.
No, there isn't.
You can make the base class property virtual, then override it to throw an exception in the setter, but there's no way to give a compile-time error. After all, there is nothing you do at compile time to prevent
(elmo.Manager as Employee).Manager = new Manager();
However, you can write
public class ManagerEmployee : Emp {
public new ManagerEmployee Manager {
get { return base.Manager; }
}
}
Note that this won't prevent casting.
Like most things, it depends. Given the following classes:
public class foo
{
public string Test { get { return "foo"; } }
}
public class bar : foo
{
public new string Test { get { return "bar"; } }
}
And the following code:
bar a = new bar();
// returns bar
literalTest1.Text = a.Test;
foo b = new foo();
// returns "foo"
literalTest2.Text = b.Test;
foo c = new bar();
// returns "foo"
literalTest3.Text = c.Test;
You can see, based on the comments above, that you can override a property that is not declared as virtual. However, the overridden property will only be used when the object variable is declared as the type that overrides the property - not as any of its ancestors. This effectively breaks polymorphism.
Fix your ancestor class instead.
As others have said. No. I'll add that if not every employee has a manager and an assistant, then your inheritance hierarchy is wrong. It would seem that the only thing an employee and manager share is a name. You can add via inheritance, but you cannot take away via inheritance.
No you can't do this, and you wouldn't want to - either Manager is an Employee and has a Manager and an Assistant, or it doesn't and hence should have a different base class i.e. this situation indicates a design flaw. One possibility could be to return null for these properties though if that makes sense for the domain.

Why cast to an interface?

In Jesse Liberty's Programming C# (p.142) he provides an example where he casts an object to an interface.
interface IStorable
{
...
}
public class Document : IStorable
{
...
}
...
IStorable isDoc = (IStorable) doc;
...
What is the point of this, particularly if the object's class implements the inteface anyway?
EDIT1: To clarify, I'm interested in the reason for the cast (if any), not the reason for implementing interfaces. Also, the book is his 2001 First Edition (based on C#1 so the example may not be germane for later versions of C#).
EDIT2: I added some context to the code
Because you want to restrict yourself to only methods provided by the interface. If you use the class, you run the risk of calling a method (inadvertently) that's not part of the interface.
There is only one reason when you actually need a cast: When doc is of a base type of an actual object that implements IStorable. Let me explain:
public class DocBase
{
public virtual void DoSomething()
{
}
}
public class Document : DocBase, IStorable
{
public override void DoSomething()
{
// Some implementation
base.DoSomething();
}
#region IStorable Members
public void Store()
{
// Implement this one aswell..
throw new NotImplementedException();
}
#endregion
}
public class Program
{
static void Main()
{
DocBase doc = new Document();
// Now you will need a cast to reach IStorable members
IStorable storable = (IStorable)doc;
}
}
public interface IStorable
{
void Store();
}
If the object implements the interface explicitly (public void IStorable.StoreThis(...)) that casting is the easiest way to actually reach the interface members.
I am not sure under what context the example was given in the book. But, you generally can type cast an object to interface to achieve multiple inheritance. I have given the example below.
public interface IFoo
{
void Display();
}
public interface IBar
{
void Display();
}
public class MyClass : IFoo, IBar
{
void IBar.Display()
{
Console.WriteLine("IBar implementation");
}
void IFoo.Display()
{
Console.WriteLine("IFoo implementation");
}
}
public static void Main()
{
MyClass c = new MyClass();
IBar b = c as IBar;
IFoo f = c as IFoo;
b.Display();
f.Display();
Console.ReadLine();
}
This would display
IBar implementation
IFoo implementation
It's pretty hard to tell without more of the context. If the variable doc is declared to be a type which implements the interface, then the cast is redundant.
Which version of the book are you reading? If it's "Programming C# 3.0" I'll have a look tonight when I'm at home.
EDIT: As we've seen in the answers so far, there are three potential questions here:
Why cast in the statement shown in the question? (Answer: you don't have to if doc is of an appropriate compile-time type)
Why is it ever appropriate to explicitly cast to an implemented interface or base class? (Answer: explicit interface implementation as shown in another answer, and also for the sake of picking a less specific overload when passing the cast value as an argument.)
Why use the interface at all? (Answer: working with the interface type means you're less susceptible to changes in the concrete type later on.)
The doc object might be of a type that implements members of IStorable explicitly, not adding them to the classes primary interface (i.e., they can only be called via the interface).
Actually "casting" (using the (T) syntax) does not make any sense since C# handles upcasts (cast to parent type) automatically (unlike F# for instance).
There are a lot of good answers here, but I don't really think they answer WHY you actually WANT to use the most restrictive interface possible.
The reasons do not involve your initial coding, they involve the next time you visit or refactor the code--or when someone else does it.
Let's say you want a button and are placing it on your screen. You are getting the button either passed in or from another function, like this:
Button x=otherObject.getVisibleThingy();
frame.add(x);
You happen to know that VisibleThingy is a button, it returns a button, so everything is cool here (no cast required).
Now, lets say that you refactor VisibleThingy to return a toggle button instead. You now have to refactor your method because you knew too much about the implementation.
Since you only NEED the methods in Component (a parent of both button and Toggle, which could have been an interface--same thing pretty much for our purposes), if you had written that first line like this:
Component x=(Component)otherObject.getVisibleThingy();
You wouldn't have had to refactor anything--it would have just worked.
This is a very simple case, but it can be much more complex.
So I guess the summary would be that an interface is a specific way to "View" your object--like looking at it through a filter...you can only see some parts. If you can restrict your view enough, the object can "Morph" behind your particular view and not effect anything in your current world--a very powerful trick of abstraction.
The best reason why you would cast to interfaces would be if you are writing code against objects and you don't know what concrete type they are and you don't want to.
If you know that you might come across an object that implements a specific interface you could then get the values out of the object without having to know the concrete class that this object is. Also, if you know that an object implements a given interface, that interface might define methods that you can execute to take certain actions on the object.
Here's a simple example:
public interface IText
{
string Text { get; }
}
public interface ISuperDooper
{
string WhyAmISuperDooper { get; }
}
public class Control
{
public int ID { get; set; }
}
public class TextControl : Control, IText
{
public string Text { get; set; }
}
public class AnotherTextControl : Control, IText
{
public string Text { get; set; }
}
public class SuperDooperControl : Control, ISuperDooper
{
public string WhyAmISuperDooper { get; set; }
}
public class TestProgram
{
static void Main(string[] args)
{
List<Control> controls = new List<Control>
{
new TextControl
{
ID = 1,
Text = "I'm a text control"
},
new AnotherTextControl
{
ID = 2,
Text = "I'm another text control"
},
new SuperDooperControl
{
ID = 3,
WhyAmISuperDooper = "Just Because"
}
};
DoSomething(controls);
}
static void DoSomething(List<Control> controls)
{
foreach(Control control in controls)
{
// write out the ID of the control
Console.WriteLine("ID: {0}", control.ID);
// if this control is a Text control, get the text value from it.
if (control is IText)
Console.WriteLine("Text: {0}", ((IText)control).Text);
// if this control is a SuperDooperControl control, get why
if (control is ISuperDooper)
Console.WriteLine("Text: {0}",
((ISuperDooper)control).WhyAmISuperDooper);
}
}
}
running this little program would give you the following output:
ID: 1
Text: I'm a text control
ID: 2
Text: I'm another text control
ID: 3
Text: Just Because
Notice that I didn't have to write any code in the DoSomething method that required me to know anything about all the objects I was working on being concrete object types. The only thing that I know is that I'm working on objects that are at least an instance of the Control class. I can then use the interface to find out what else they might have.
There's a million different reasons that you would take this approach with interfaces on your objects but it gives you a loose way to access your objects without having to know exactly what it is.
Think of all the credit cards in the world, every company makes their own, the interface is the same though, so every card reader can have a card swiped through it that follows the standard. Similar to the usage of interfaces.
As has been noted, the casting is superfluous and not necessary. However, it is a more explicit form of coding which would be useful to beginners in aiding their understanding.
In an introductory textbook, it is best to explicitly act, rather than let the compliler do things implicitly, which would be more confusing for beginners.
The "doc" is not of type "IStorable" so it would be confusing for beginners to see that it is being assigned to a isDoc. By explicitly casting, the author (of the book and of the code) is saying that a document can be casted to an IStorable object, but it is NOT THE SAME as an IStorable object.
The point is, the object (where did you get it?) may not implement the interface, in which case an exception is thrown which can be caught and dealt with. Of course you can use the "is" operator to check, and the "as" operator to cast instead of the C-style cast.
To allow for the most decoupling between pieces of code...
See the following article for more:
Interfaces
The main reason you would explicitly cast to an interface is if the members of the interface are implemented explicitly (i.e. with fully-qualified names in the form of InterfaceName.InterfaceMemberName). This is because when you fully-qualify them with the interface name, those members are not actually part of the implementing class's API. You can only get to them via casting to the interface.
Here's an example you can run as-is:
using System;
public interface ISomethingDoer {
void DoSomething();
}
public class ThingA : ISomethingDoer {
public void DoSomething(){
Console.WriteLine("ThingA did it!");
}
}
public class ThingB : ISomethingDoer {
// This is implemented explicitly by fully-qualifying it with the interface name
// Note no 'scope' here (e.g. public, etc.)
void ISomethingDoer.DoSomething(){
Console.WriteLine("ThingB did it!");
}
}
public static class Runner {
public static void Main(){
var a = new ThingA();
a.DoSomething(); // Prints 'ThingA did it!'
var b = new ThingB();
b.DoSomething(); // NOTE: THIS WILL NOT COMPILE!!!
var bSomethingDoer = (ISomethingDoer)b;
bSomethingDoer.DoSomething(); // Prints 'ThingB did it!'
}
}
HTH!

Categories

Resources