15.02.2015 Views

C# 4 and .NET 4

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

104 ❘ ChaPTer 4 inheritAnce<br />

The main point to notice about this code is the way that you have declared both your reference variables as<br />

IBankAccount references. This means that they can point to any instance of any class that implements this<br />

interface. However, it also means that you can call only methods that are part of this interface through these<br />

references — if you want to call any methods implemented by a class that are not part of the interface, you<br />

need to cast the reference to the appropriate type. In the example code, you were able to call ToString()<br />

(not implemented by IBankAccount) without any explicit cast, purely because ToString() is a System.<br />

Object method, so the <strong>C#</strong> compiler knows that it will be supported by any class (put differently, the cast<br />

from any interface to System.Object is implicit). Chapter 7, “Operators <strong>and</strong> Casts,” covers the syntax for<br />

how to perform casts.<br />

Interface references can in all respects be treated as class references — but the power of an interface<br />

reference is that it can refer to any class that implements that interface. For example, this allows you to form<br />

arrays of interfaces, where each element of the array is a different class:<br />

IBankAccount[] accounts = new IBankAccount[2];<br />

accounts[0] = new SaverAccount();<br />

accounts[1] = new GoldAccount();<br />

Note, however, that we’d get a compiler error if we tried something like this:<br />

accounts[1] = new SomeOtherClass();<br />

This causes a compilation error similar to this:<br />

// SomeOtherClass does NOT implement<br />

// IBankAccount: WRONG!!<br />

Cannot implicitly convert type 'Wrox.ProCSharp. SomeOtherClass' to<br />

'Wrox.ProCSharp.IBankAccount'<br />

derived interfaces<br />

It’s possible for interfaces to inherit from each other in the same way that classes do. This concept<br />

is illustrated by defining a new interface, ITransferBankAccount, which has the same features as<br />

IBankAccount but also defines a method to transfer money directly to a different account:<br />

namespace Wrox.ProCSharp<br />

{<br />

public interface ITransferBankAccount: IBankAccount<br />

{<br />

bool TransferTo(IBankAccount destination, decimal amount);<br />

}<br />

}<br />

Because ITransferBankAccount is derived from IBankAccount, it gets all the members of IBankAccount<br />

as well as its own. That means that any class that implements (derives from) ITransferBankAccount<br />

must implement all the methods of IBankAccount, as well as the new TransferTo() method defined in<br />

ITransferBankAccount. Failure to implement all these methods will result in a compilation error.<br />

Note that the TransferTo() method uses an IBankAccount interface reference for the destination account.<br />

This illustrates the usefulness of interfaces: When implementing <strong>and</strong> then invoking this method, you don’t<br />

need to know anything about what type of object you are transferring money to — all you need to know is<br />

that this object implements IBankAccount.<br />

To illustrate ITransferBankAccount, assume that the Planetary Bank of Jupiter also offers a current<br />

account. Most of the implementation of the CurrentAccount class is identical to the implementations of<br />

SaverAccount <strong>and</strong> GoldAccount (again, this is just to keep this example simple — that won’t normally be<br />

the case), so in the following code just the differences are highlighted:<br />

public class CurrentAccount: ITransferBankAccount<br />

{<br />

private decimal balance;<br />

public void PayIn(decimal amount)<br />

{<br />

balance += amount;<br />

}<br />

www.it-ebooks.info

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!