Casting between the Implementing Class and Its Interfaces

Just as with a derived class and a base type, casting from an object to its implemented interface is an implicit cast. No cast operator is required because an instance of the implementing class will always contain all the members in the interface, and therefore, the object will always cast successfully to the interface type.

Although the cast will always be successful from the implementing class to the implemented interface, many different classes could implement a particular interface, so you can never be certain that a downward cast from the interface to the implementing class will be successful. The result is that casting from an interface to its implementing class requires an explicit cast.

Interface Inheritance

Interfaces can derive from each other, resulting in an interface that inherits all the members in its base interfaces. As shown in Listing 7.6, the interfaces directly derived from IReadableSettingsProvider are the explicit base interfaces.

Listing 7.6. Deriving One Interface from Another

 interface IReadableSettingsProvider {     string GetSetting(string name, string defaultValue); } interface ISettingsProvider : IReadableSettingsProvider {     void SetSetting(string name, string value); } class FileSettingsProvider : ISettingsProvider {     #region ISettingsProvider Members     public void SetSetting(string name, string value)     {         // ...     }     #endregion     #region IReadableSettingsProvider Members     public string GetSetting(string name, string defaultValue)     {         // ...     }     #endregion } 

In this case, ISettingsProvider derives from IReadableSettingsProvider and, therefore, inherits its members. If IReadableSettingsProvider also had an explicit base interface, ISettingsProvider would inherit those members too, and the full set of interfaces in the derivation hierarchy would simply be the accumulation of base interfaces.

It is interesting to note that if GetSetting() is implemented explicitly, it must be done using IReadableSettingsProvider. The declaration with ISettingsProvider in Listing 7.7 will not compile.

Listing 7.7. Explicit Member Declaration without the Containing Interface (Failure)

 // ERROR: GetSetting() not available on ISettingsProvider string ISettingsProvider.GetSetting(   string name, string defaultValue) {   // ... } 

The results of Listing 7.7 appear in Output 7.2.

Output 7.2.

 'ISettingsProvider.GetSetting' in explicit interface declaration is not a member of interface. 

This output appears in addition to an error indicating that IReadableSettingsProvider.GetSetting() is not implemented. The fully qualified interface member name used for explicit interface member implementation must reference the interface name in which it was originally declared.

Even though a class implements an interface (ISettingsProvider) which is derived from a base interface (IReadableSettingsProvider), the class can still declare implementation of both interfaces overtly, as Listing 7.8 demonstrates.

Listing 7.8. Using a Base Interface in the Class Declaration

 class FileSettingsProvider : ISettingsProvider,      IReadableSettingsProvider                            {     #region ISettingsProvider Members     public void SetSetting(string name, string value)     {         // ...     }     #endregion     #region IReadableSettingsProvider Members     public string GetSetting(string name, string defaultValue)     {         // ...     }     #endregion } 

In this listing, there is no change to the interface's implementations on the class, and although the additional interface implementation declaration on the class header is superfluous, it can provide better readability.

The decision to provide multiple interfaces rather than just one combined interface depends largely on what the interface designer wants to require of the implementing class. By providing an IReadableSettingsProvider interface, the designer communicates that implementers are only required to implement a settings provider that retrieves settings. They do not have to be able to write to those settings. This reduces the implementation burden by not imposing the complexities of writing settings as well.

In contrast, implementing ISettingsProvider assumes that there is never a reason to have a class that can write settings without reading them. The inheritance relationship between ISettingsProvider and IReadableSettingsProvider, therefore, forces the combined total of both interfaces on the ISettingsProvider class.

Essential C# 2.0
Essential C# 2.0
ISBN: 0321150775
EAN: 2147483647
Year: 2007
Pages: 185 © 2008-2017.
If you may any questions please contact us: