Download presentation
Presentation is loading. Please wait.
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. byte Points { get; }
3
the Hexagon), while others (such as the Circle) do not.
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
public struct SomeStruct : ISomeInterface, IPointy
//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
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 public static void Main() ...... // Catch a possible InvalidCastException Circle c = new Circle(“John"); IPointy ipt; try { ipt = (IPointy)c;//boxing or explicit casting Console.WriteLine(ipt.Points); } catch (InvalidCastException e) Console.WriteLine(e.Message);
9
Obtaining Interface References: The is Keyword
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; if(ipt != null) Console.WriteLine("Points: {0}", ipt.Points); else Console.WriteLine("OOPS! Not pointy..."); } Obtaining Interface References: The is Keyword //third way to test for an interface Triangle t = new Triangle(); 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
Interfaces As Parameters
{ // 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 // Models the ability to render a type in stunning 3D. public interface IDraw3D void Draw3D(); // Circle supports IDraw3D public class Circle : Shape, IDraw3D ... public void Draw3D() Console.WriteLine("Drawing Circle in 3D!"); // Hexagon supports IPointy and IDraw3D public class Hexagon : Shape, IPointy, IDraw3D { ... public void Draw3D() Console.WriteLine("Drawing Hexagon in 3D!"); }
11
public interface IDrawable { void Draw(); }
Building Interface Hierarchies // The base interface. public interface IDrawable { void Draw(); } public interface IPrintable : IDrawable void Print(); public interface IMetaFileRender : IPrintable void Render(); // 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.");
12
// Exercise the interfaces. static void Main(string[] args) {
// 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."); // Exercise the interfaces. static void Main(string[] args) { SuperImage si = new SuperImage(); // 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
Responsible for implementing TurboBoost(), Dive(), and Drive():
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
Here, we will examine the role of IEnumerable and IEnumerator
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: // 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 // This seems reasonable... public class Program { static void Main(string[] args) Garage carLot = new Garage(); foreach (Car c in carLot) Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrSpeed); }
16
// This interface allows the caller to obtain a container's subitems.
// 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 (); // Advance the internal position of the cursor. 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:
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. IDictionary Allows an object to represent its contents using name/value pairs. IDictionaryEnumerator Enumerates the contents of a type supporting IDictionary. IEnumerable Returns the IEnumerator interface for a given object. IEnumerator Generally supports foreach-style iteration of subtypes. IHashCodeProvider Returns the hash code for the implementing type using a customized hash algorithm. IList Provides behavior to add, remove, and index items in a list of objects.
19
System.Collections Class Key Implemented Interfaces
The Class Types of System.Collections System.Collections Class Meaning Key Implemented Interfaces ArrayList Represents a dynamically sized array of objects. IList, ICollection, IEnumerable, and ICloneable Hashtable Represents a collection of objects identified by a numerical key. Custom types stored in a Hashtable should always override System.Object.GetHashCode(). IDictionary, ICollection, IEnumerable, and ICloneable Queue Represents a standard first-in, first-out (FIFO) queue. ICollection, ICloneable, and IEnumerable SortedList Like a dictionary; however, the elements can also be accessed by ordinal position (e.g., index). Stack A last-in, first-out (LIFO) queue providing push and pop (and peek) functionality. ICollection, ICloneable, and IEnumerable 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)); // 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
System.Collection.Queue
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 System.Collection.Queue Meaning Dequeue() Removes and returns the object at the beginning of the Queue Enqueue() Adds an object to the end of the Queue 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;
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.