Definition : nothing more than a named set of abstract members
Interface Types vs. Abstract Base Classes
Interfaces only contain abstract member definitions
In inheritance, abstract doesn't support multiple inheritance, interface does.
passing object by interface
1.Using Exception : InvalidCastException
2.Obtaining Interface References by askeyword
3.Obtainting Interface References by iskeyword
Providing Many Interfaces have same method, how to implement the method in a derived class which is inherited from all interfaces
How to call multiple inheritance method
If you want access array of your types by FOREACH keyword, your type must be enumerable.
To do so, the best way is inherit IEnumerable.
How it works :
Building Iterator Methods with the yield keyword
See return type, it's not IEnumerator
the IColneable interace makes possible to implement deep copy objects
Building Comparable Objects (IComparable)
Problem Sources
Solutions
an Example for String
Interface Types vs. Abstract Base Classes
Interfaces only contain abstract member definitions
In inheritance, abstract doesn't support multiple inheritance, interface does.
passing object by interface
class Program { static void Main(String[] args) { // All of these classes support the ICloneable interface. string myStr = "Hello"; OperatingSystem unixOS = new OperatingSystem(PlatformID.Unix, new Version()); System.Data.SqlClient.SqlConnection sqlCnn = new System.Data.SqlClient.SqlConnection(); // Therefore, they can all be passed into a method taking ICloneable. CloneMe(myStr); CloneMe(unixOS); CloneMe(sqlCnn); Console.ReadLine(); } private static void CloneMe(ICloneable c) { // Clone whatever we get and print out the name. object theClone = c.Clone(); Console.WriteLine("Your clone is a: {0}", theClone.GetType().Name); } }abstract class
class Program abstract class Shape { ... // Every derived class must now support this method! public abstract byte GetNumberOfPoints(); }Error condition for Interface
public interface IPointy { // Error! Interfaces cannot have fields! public int numbOfPoints; // Error! Interfaces do not have constructors! public IPointy() { numbOfPoints = 0;}; // Error! Interfaces don't provide an implementation of members! byte GetNumberOfPoints() { return numbOfPoints; } // A read-write property in an interface would look like: // retType PropName { get; set; } // while a write-only property in an interface would be: // retType PropName { set; } byte Points { get; } } ...... // Ack! Illegal to allocate interface types. static void Main(string[] args) { IPointy p = new IPointy(); // Compiler error! }Implementing an Interface
// This class derives from System.Object and // implements a single interface. public class Pencil : IPointy {...} // This class also derives from System.Object // and implements a single interface. public class SwitchBlade : object, IPointy {...} // This class derives from a custom base class // and implements a single interface. public class Fork : Utensil, IPointy {...} // This struct implicitly derives from System.ValueType and // implements two interfaces. public struct Arrow : ICloneable, IPointy {...}Determine a class or structure supports a specific interface?
1.Using Exception : InvalidCastException
static void Main(string[] args) { ... // Catch a possible InvalidCastException. Circle c = new Circle("Lisa"); IPointy itfPt = null; try { itfPt = (IPointy)c; Console.WriteLine(itfPt.Points); } catch (InvalidCastException e) { Console.WriteLine(e.Message); } .... }
2.Obtaining Interface References by askeyword
static void Main(string[] args) { ... // Can we treat hex2 as IPointy? Hexagon hex2 = new Hexagon("Peter"); IPointy itfPt2 = hex2 as IPointy; //if not, return null ★★★ if(itfPt2 != null) Console.WriteLine("Points: {0}", itfPt2.Points); else Console.WriteLine("OOPS! Not pointy..."); }
3.Obtainting Interface References by iskeyword
static void Main(string[] args) { Console.WriteLine("***** Fun with Interfaces *****\n"); // Make an array of Shapes. Shape[] myShapes = { new Hexagon(), new Circle(), new Triangle("Joe"), new Circle("JoJo")} ; for(int i = 0; i < myShapes.Length; i++) { // Recall the Shape base class defines an abstract Draw() // member, so all shapes know how to draw themselves. myShapes[i].Draw(); // Who's pointy? if(myShapes[i] is IPointy) //is keywrod ★★★ Console.WriteLine("-> Points: {0}", ((IPointy) myShapes[i]).Points); else Console.WriteLine("-> {0}\'s not pointy!", myShapes[i].PetName); Console.WriteLine(); } Console.ReadLine(); }Interfaces As Parameters
// I'll draw anyone supporting IDraw3D. static void DrawIn3D(IDraw3D itf3d) { Console.WriteLine("-> Drawing IDraw3D compatible type"); itf3d.Draw3D(); } passing interface type by parameter ..... // Can I draw you in 3D? if(myShapes[i] is IDraw3D) DrawIn3D((IDraw3D)myShapes[i]); .....Interfaces As Return Values
static IPointy FindFirstPointyShape(Shape[] shapes) { ....} // Get first pointy item. // To be safe, you'd want to check firstPointyItem for null before proceeding. IPointy firstPointyItem = FindFirstPointyShape(myShapes);Resolving Name Clashes via Explicit Interface Implementation
Providing Many Interfaces have same method, how to implement the method in a derived class which is inherited from all interfaces
// Draw image to a Form. public interface IDrawToForm { void Draw(); } // Draw to buffer in memory. public interface IDrawToMemory { void Draw(); } // Render to the printer. public interface IDrawToPrinter { void Draw(); } Solution 1 // All of these invocations call the // same Draw() method! Octagon oct = new Octagon(); oct.Draw(); IDrawToForm itfForm = (IDrawToForm)oct; itfForm.Draw(); IDrawToPrinter itfPriner = (IDrawToPrinter)oct; itfPriner.Draw(); IDrawToMemory itfMemory = (IDrawToMemory)oct; itfMemory.Draw(); Solution2 class Octagon : IDrawToForm, IDrawToMemory, IDrawToPrinter { // Explicitly bind Draw() implementations // to a given interface. void IDrawToForm.Draw() { Console.WriteLine("Drawing to form..."); } void IDrawToMemory.Draw() { Console.WriteLine("Drawing to memory..."); } void IDrawToPrinter.Draw() { Console.WriteLine("Drawing to a printer..."); } } but not this way // Error! No access modifer! public void IDrawToForm.Draw() { Console.WriteLine("Drawing to form..."); }
How to call multiple inheritance method
Octagon oct = new Octagon(); // We now must use casting to access the Draw() // members. IDrawToForm itfForm = (IDrawToForm)oct; itfForm.Draw(); // Shorthand notation if you don't need // the interface variable for later use. ((IDrawToPrinter)oct).Draw(); // Could also use the "as" keyword. if(oct is IDrawToMemory) ((IDrawToMemory)oct).Draw();Building Enumerable Types (IEnumerable and IEnumerator)
If you want access array of your types by FOREACH keyword, your type must be enumerable.
To do so, the best way is inherit IEnumerable.
using System.Collections; ... public class Garage : IEnumerable { // System.Array already implements IEnumerator! private Car[] carArray = new Car[4]; public Garage() { 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(); } }
How it works :
Building Iterator Methods with the yield keyword
public class Garage { private Car[] carArray = new Car[4]; ... // Iterator method. public IEnumerator GetEnumerator() { foreach (Car c in carArray) { yield return c; } } }Building a Named Iterator
See return type, it's not IEnumerator
public IEnumerable GetTheCars(bool ReturnRevesed) { // Return the items in reverse. if (ReturnRevesed) { for (int i = carArray.Length; i != 0; i--) { yield return carArray[i-1]; } } else { // Return the items as placed in the array. foreach (Car c in carArray) { yield return c; } } } static void Main(string[] args) { Console.WriteLine("***** Fun with the Yield Keyword *****\n"); Garage carLot = new Garage(); // Get items using GetEnumerator(). foreach (Car c in carLot) { Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrentSpeed); } Console.WriteLine(); // Get items (in reverse!) using named iterator. foreach (Car c in carLot.GetTheCars(true)) <--------------if incoming parameter is "true" { Console.WriteLine("{0} is going {1} MPH", c.PetName, c.CurrentSpeed); }
Building Cloneable Objects (ICloneable)
// A class named Point. public class Point { public int X {get; set;} public int Y {get; set;} public Point(int xPos, int yPos) { X = xPos; Y = yPos;} public Point(){} // Override Object.ToString(). public override string ToString() { return string.Format("X = {0}; Y = {1}", X, Y ); } } public interface ICloneable { object Clone(); } // The Point now supports "clone-ability." public class Point : ICloneable { public int X { get; set; } public int Y { get; set; } public Point(int xPos, int yPos) { X = xPos; Y = yPos; } public Point() { } // Override Object.ToString(). public override string ToString() { return string.Format("X = {0}; Y = {1}", X, Y); } // Return a copy of the current object. public object Clone() { return new Point(this.X, this.Y); } } the Point type does not contain any internal reference type variables, you could simplify the implementation of the Clone() method as follows: public object Clone() { // Copy each field of the Point member by member. return this.MemberwiseClone(); }
Building Comparable Objects (IComparable)
Problem Sources
Declare User Type | Using the Type |
public class Car { ... public int CarID {get; set;} public Car(string name, int currSp, int id) { CurrentSpeed = currSp; PetName = name; CarID = id; } ... } |
static void Main(string[] args) { Console.WriteLine("*Fun with Object Sorting*\n"); int[] int_array={2,5,6,1,0,7,9,23,11}; Array.Sort(int_array); <----it will work!!! // Make an array of Car objects. Car[] myAutos = new Car[5]; myAutos[0] = new Car("Rusty", 80, 1); myAutos[1] = new Car("Mary", 40, 234); myAutos[2] = new Car("Viper", 40, 34); myAutos[3] = new Car("Mel", 40, 4); myAutos[4] = new Car("Chucky", 40, 5); Array.Sort(myAutos);<------Exception??? Console.ReadLine(); } |
Solutions
Inherit IComparable interface | IComparable Interface |
// The iteration of the Car can be ordered // based on the CarID. public class Car : IComparable { ... // IComparable implementation. int IComparable.CompareTo(object obj) { Car temp = obj as Car; if (temp != null) { if (this.CarID > temp.CarID) return 1; if (this.CarID < temp.CarID) return -1; else return 0; } else throw new ArgumentException( "Parameter is not a Car!"); } } |
// This interface allows an object to specify its // relationship between other like objects. |
an Example for String
// This helper class is used to sort an array of Cars by pet name. public class PetNameComparer : IComparer { // Test the pet name of each object. int IComparer.Compare(object o1, object o2) { Car t1 = o1 as Car; Car t2 = o2 as Car; if(t1 != null && t2 != null) return String.Compare(t1.PetName, t2.PetName); else throw new ArgumentException("Parameter is not a Car!"); } } |
static void Main(string[] args) { ... // Now sort by pet name. Array.Sort(myAutos, new PetNameComparer()); |