Understanding Interfaces in C#

Slide Note
Embed
Share

Interfaces in C# define behavior that classes or structures can choose to support. They contain abstract members and do not specify a base class. Interfaces must be implemented by classes to bring functionality. Learn how to define and implement interfaces in C# to create flexible and modular code structures.


Uploaded on Sep 08, 2024 | 1 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. Defining Interfaces using C# An interface is nothing more than a named collection of semantically related abstract members. An interface expresses a behavior that a given class or structure may choose to support. At a syntactic level, an interface is defined using the C# interface keyword. Unlike other .NET types, interfaces never specify a base class and contain members that do not take an access modifier

  2. // This interface defines the behavior of "having points." public interface IPointy { // Implicitly public and abstract. byte GetNumberOfPoints(); } The IPointy interface defines a single method. However, .NET interface types are also able to define any number of properties. For example, you could create the IPointy interface to use a read-only property rather than a traditional accessor method: // The pointy behavior as a read-only property. public interface IPointy { byte Points { get; } }

  3. You cannot allocate interface types as you would a class or structure: // Ack! Illegal to "new" interface types. static void Main(string[] args) { IPointy p = new IPointy(); // Compiler error! } * Interfaces do not bring much to the table until they are implemented by a class or structure. Here, IPointy is an interface that expresses the behavior of having points. The idea is simple: Some classes in the Shapes hierarchy have points (such as the Hexagon), while others (such as the Circle) do not. If you configure Hexagon and Triangle to implement the IPointy interface, you can safely assume that each class now supports a common behavior, and therefore a common set of members.

  4. Implementing an Interface using C# When a class (or structure) chooses to extend its functionality by supporting interface types, it does so using a comma-delimited list in the type definition. Be aware that the direct base class must be the first item listed after the colon operator. When your class type derives directly from System.Object, you are free to simply list the interface(s) supported by the class, as the C# compiler will extend your types from System.Object if you do not say otherwise. On a related note, given that structures always derive from System.ValueType. // This class derives from System.Object and implements single interface. public class SomeClass : ISomeInterface { // Some Code }

  5. //Class derives from custom base class and implements a single interface. public class AnotherClass : MyBaseClass, ISomeInterface { // Some Code } // This struct derives from System.ValueType and implements two //interfaces. public struct SomeStruct : ISomeInterface, IPointy { // Some Code }

  6. // Hexagon now implements IPointy. public class Hexagon : Shape, IPointy { public Hexagon(){ } public Hexagon(string name) : base(name){ } public override void Draw() { Console.WriteLine("Drawing {0} the Hexagon", PetName); } // IPointy Implementation. public byte Points { get { return 6; } } }

  7. // New Shape derived class named Triangle. public class Triangle : Shape, IPointy { public Triangle() { } public Triangle(string name) : base(name) { } public override void Draw() { Console.WriteLine("Drawing {0} the Triangle", PetName); } // IPointy Implementation. public byte Points { get { return 3; } } } 31, 37,39,41,42,43,45,46,

  8. Invoking Interface Members at the Object Level public static void Main(string[] args) { // Call new Points member defined by IPointy Hexagon hex = new Hexagon(); Console.WriteLine("Points: {0}", hex.Points); } This approach works fine in this particular case, given that you are well aware that the Hexagon type has implemented the interface in question. Other times, however, you will not be able to determine at compile time which interfaces are supported by a given type. Obtaining Interface References: Explicit Casting try { public static void Main() { ...... // Catch a possible InvalidCastException Circle c = new Circle( John"); IPointy ipt; ipt = (IPointy)c;//boxing or explicit casting Console.WriteLine(ipt.Points); } catch (InvalidCastException e) { Console.WriteLine(e.Message); } }

  9. Obtaining Interface References: The as Keyword public static void Main(string[] args) { ... // Can we treat hex2 as IPointy? Hexagon h = new Hexagon("Ram"); IPointy ipt = h as IPointy; Obtaining Interface References: The is Keyword //third way to test for an interface Triangle t = new Triangle(); if(ipt != null) Console.WriteLine("Points: {0}", ipt.Points); else Console.WriteLine("OOPS! Not pointy..."); } if(t is IPointy) Console.WriteLine(t.Points); Else Console.WriteLine( OOPS! Not pointy..."); Exercising the Shapes Hierarchy public static void Main(string[] args) { ... Shape[ ] s = { new Hexagon(), new Circle(), new Triangle("Ram"), new Circle("Sham")} ; for(int i = 0; i < s.Length; i++)

  10. { // Recall the Shape base class defines an abstract Draw() // member, so all shapes know how to draw themselves. s[i].Draw(); if(s[i] is IPointy) Console.WriteLine("Points: {0} ", ((IPointy)s[i]).Points); else Console.WriteLine("{0} is not a pointy!", s[i].PetName); } } Interfaces As Parameters public interface IDraw3D { void Draw3D(); } // Circle supports IDraw3D public class Circle : Shape, IDraw3D { ... public void Draw3D() { Console.WriteLine("Drawing Circle in 3D!"); } } // Models the ability to render a type in stunning 3D. // Hexagon supports IPointy and IDraw3D public class Hexagon : Shape, IPointy, IDraw3D { ... public void Draw3D() { Console.WriteLine("Drawing Hexagon in 3D!"); } }

  11. Building Interface Hierarchies // This class supports IDrawable, IPrintable, and IMetaFileRender. public class SuperImage : IMetaFileRender { public void Draw() { Console.WriteLine("Basic drawing logic."); } // The base interface. public interface IDrawable { void Draw(); } public interface IPrintable : IDrawable { void Print(); } public void Print() { Console.WriteLine("Draw to printer."); } public interface IMetaFileRender : IPrintable { void Render(); } public void Render() { Console.WriteLine("Render to metafile."); } }

  12. // This class supports IDrawable, IPrintable, and IMetaFileRender. public class SuperImage : IMetaFileRender { public void Draw() { Console.WriteLine("Basic drawing logic."); } public void Print() { Console.WriteLine("Draw to printer."); } public void Render() { Console.WriteLine("Render to metafile."); } } static void Main(string[] args) { SuperImage si = new SuperImage(); // Exercise the interfaces. // Get IDrawable. IDrawable itfDraw = (IDrawable)si; itfDraw.Draw(); // Now get ImetaFileRender, which exposes all methods up // the chain of inheritance. if (itfDraw is IMetaFileRender) { IMetaFileRender itfMF = (IMetaFileRender)itfDraw; itfMF.Render(); itfMF.Print(); } }

  13. Interfaces with Multiple Base Interfaces public interface ICar { void Drive(); } public interface IUnderwaterCar { void Dive(); } // Here we have an interface with TWO base interfaces. public interface IJamesBondCar : ICar, IUnderwaterCar { void TurboBoost(); } If you were to build a class that implements IJamesBondCar, you would now be Responsible for implementing TurboBoost(), Dive(), and Drive():

  14. public class JamesBondCar : IJamesBondCar { public void Drive() { Console.WriteLine("Speeding up..."); } public void Dive() { Console.WriteLine("Submerging..."); } public void TurboBoost() { Console.WriteLine("Blast off!"); } } This specialized automobile can now be manipulated as you would expect: static void Main(string[] args) { ... JamesBondCar j = new JamesBondCar(); j.Drive(); j.TurboBoost(); j.Dive(); }

  15. Building a Custom Enumerator (IEnumerable and IEnumerator) Here, we will examine the role of IEnumerable and IEnumerator Assume you have developed a class named Garage that contains a set of individual Car types stored within a System.Array: // This seems reasonable... public class Program { static void Main(string[] args) { Garage carLot = new Garage(); // Garage contains a set of Car objects. public class Garage { private Car[] carArray; // Fill with some Car objects upon startup. public Garage() { carArray = new Car[4]; carArray[0] = new Car("Rusty", 30); carArray[1] = new Car("Clunker", 55); carArray[2] = new Car("Zippy", 30); carArray[3] = new Car("Fred", 30); } } The compiler informs you that the Garage class does not implement a method named GetEnumerator(). This method is formalized by the IEnumerable interface, which is found lurking within the System.Collections namespace foreach (Car c in carLot) { Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrSpeed); } } }

  16. // This interface informs the caller that the object's subitems can // be enumerated. public interface IEnumerable { IEnumerator GetEnumerator(); } The GetEnumerator() method returns a reference to yet another interface named System.Collections.IEnumerator. This interface provides the infrastructure to allow the caller to traverse the internal objects contained by the IEnumerable-compatible container: // This interface allows the caller to obtain a container's subitems. public interface IEnumerator { bool MoveNext (); object Current { get;} // Get the current item (read-only property). void Reset (); // Reset the cursor before the first member. } As the System.Array type (as well as many other types) already implements IEnumerable and IEnumerator, you can simply delegate the request to the System.Array as follows: // Advance the internal position of the cursor.

  17. using System.Collections; ... public class Garage : IEnumerable { // System.Array already implements IEnumerator! private Car[] carArray; public Garage() { carArray = new Car[4]; carArray[0] = new Car("FeeFee", 200, 0); carArray[1] = new Car("Clunker", 90, 0); carArray[2] = new Car("Zippy", 30, 0); carArray[3] = new Car("Fred", 30, 0); } public IEnumerator GetEnumerator() { // Return the array object's IEnumerator. return carArray.GetEnumerator(); } } // Manually work with IEnumerator. IEnumerator i = carLot.GetEnumerator(); i.MoveNext(); Car myCar = (Car)i.Current; Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrSpeed);

  18. Exploring the System.Collections Namespace The System.Collections namespace defines a number of interfaces. System.Collections Interface Meaning ICollection Defines generic characteristics (e.g., count and thread safety) for a collection type. IComparer Defines methods to support the comparison of objects for equality. Allows an object to represent its contents using name/value pairs. Enumerates the contents of a type supporting IDictionary. Returns the IEnumerator interface for a given object. Generally supports foreach-style subtypes. Returns the hash code for the implementing type using a customized hash algorithm. IDictionary IDictionaryEnumerator IEnumerable IEnumerator iteration of IHashCodeProvider IList Provides behavior to add, remove, and index items in a list of objects.

  19. The Class Types of System.Collections System.Collections Class Meaning Key Implemented Interfaces IList, ICollection, IEnumerable, ICloneable IDictionary, ICollection, IEnumerable, ICloneable ICollection, ICloneable, IEnumerable IDictionary, ICollection, IEnumerable, ICloneable ICollection, ICloneable, and IEnumerable ArrayList Represents a dynamically sized array of objects. and Hashtable Represents a collection of objects identified by a numerical key. Custom types stored in a Hashtable should always override System.Object.GetHashCode(). Represents a standard first-in, first-out (FIFO) queue. and Queue and SortedList Like a dictionary; however, the elements can also be accessed by ordinal position (e.g., index). and Stack A last-in, first-out (LIFO) queue providing push and pop (and peek) functionality. Working with the ArrayList Type The ArrayList type is bound to be your most frequently used type in the System.Collections namespace in that it allows you to dynamically resize the contents at your whim

  20. static void Main(string[] args) { // Create ArrayList and fill with some initial values. ArrayList carArList = new ArrayList(); carArList.AddRange(new Car[ ] { new Car("Fred", 90, 10), new Car("Mary", 100, 50), new Car("MB", 190, 11)}); Console.WriteLine("Items in carArList: {0}", carArList.Count); // Print out current values. foreach(Car c in carArList) Console.WriteLine("Car pet name: {0}", c.PetName); // Insert a new item. Console.WriteLine("\n->Inserting new Car."); carArList.Insert(2, new Car("TheNewCar", 0, 12)); Console.WriteLine("Items in carArList: {0}", carArList.Count); // Get object array from ArrayList and print again. object[] arrayOfCars = carArList.ToArray(); for(int i = 0; i < arrayOfCars.Length; i++) { Console.WriteLine("Car pet name: {0}", (Car)arrayOfCars[i]).PetName); } } Here you are making use of the AddRange() method to populate your ArrayList with a set of Car types

  21. Working with the Queue Type Queues are containers that ensure items are accessed using a first-in, first-out manner. When you are modeling a scenario in which items are handled on a first-come, first-served basis, System.Collections.Queue is your type of choice. Member of Meaning System.Collection.Queue Dequeue() Removes and returns the object at the beginning of the Queue Adds an object to the end of the Queue Enqueue() Peek() Returns the object at the beginning of the Queue without removing it Building Comparable Objects (IComparable) The System.IComparable interface specifies a behavior that allows an object to be sorted based on some specified key. Here is the formal definition: // This interface allows an object to specify its relationship //between other like objects. public interface IComparable { int CompareTo(object o); }

  22. public class Car { ... private int carID; public int ID { get { return carID; } set { carID = value; } } public Car(string name, int currSp, int id) { currSpeed = currSp; petName = name; carID = id; } ... }

Related


More Related Content