繼承與多型 (inheritance and polymorphism)

159
1 繼繼繼繼繼 繼繼繼繼繼 (Inheritance and Polym (Inheritance and Polym orphism) orphism) 鄭鄭鄭 鄭鄭鄭 鄭鄭鄭鄭鄭鄭 鄭鄭鄭鄭鄭鄭 鄭鄭鄭鄭鄭鄭 鄭鄭鄭鄭鄭鄭 / / 鄭鄭鄭鄭鄭鄭鄭 鄭鄭鄭鄭鄭鄭鄭 / / 鄭鄭鄭鄭鄭鄭鄭 鄭鄭鄭 鄭鄭鄭鄭鄭鄭鄭 鄭鄭鄭

Upload: alfreda-dawson

Post on 03-Jan-2016

35 views

Category:

Documents


4 download

DESCRIPTION

繼承與多型 (Inheritance and Polymorphism). 鄭士康 國立台灣大學 電機工程學系 / 電信工程研究所 / 資訊網路與多媒體研究所. 綱要. 繼承 修飾語 protected 限制繼承 繼承架構下的建構函式呼叫 OCP: 開放 - 封閉原理 多型 覆寫與隱藏 二十一點模擬程式 0.1 版. 綱要. 預設類別 System.Object LSP: Liskov 替代性原理 抽象類別 DIP: 依存性反轉原理 介面 ISP: 介面分離原理 多重介面 *多重介面鑄形. 綱要. 繼承 修飾語 protected - PowerPoint PPT Presentation

TRANSCRIPT

  • (Inheritance and Polymorphism)//

  • protectedOCP:-0.1

  • System.ObjectLSP: LiskovDIP: ISP: *

  • protectedOCP:-0.1

  • UsingInheritance.Calculator public int Add(int a, int b) { int result = a + b; return result;}public int Subtract(int a, int b){ int result = a - b; return result;}public int Multiply(int a, int b){ int result = a * b; return result;}

  • UsingInheritance.Program.Main (1/2)switch (op){case +: result = AdvancedCalculator.Add(operand1,operand2); Console.WriteLine("{0} + {1} = {2} ", operand1, operand2, result); break;. . .

  • UsingInheritance.Program.Main (2/2)case ^:result = AdvancedCalculator.Power(operand1,operand2); Console.WriteLine( " {0} ^ {1} = {2}",operand1, operand2, result); break;. . .}

  • UsingInheritance.AdvancedCalculator class AdvancedCalculator : Calculator{ public static int Power(int a, int b) { int result = (int)Math.Pow(a, b); return result; }}

  • UML

  • class A {private int data1;private int data2; //other members are methods}

    class B : A {private int data3; //other members are methods}

    class C : B {private int data1;private int data4; //other members are methods}

  • A a = new A();B b = new B();C c = new C();data1data2data1data2data3abdata1data2data3data1data4c

  • DataMemberInheritance.Aclass A { private int data1; private int data2; public A() { data1 = 1; data2 = 2; } public void GetAData(out int data1, out int data2) { data1 = this.data1; data2 = this.data2; }}

  • DataMemberInheritance.Bclass B : A { private int data3; public B() { data3 = 3; } public void GetBData(out int data3) { data3 = this.data3; }}

  • DataMemberInheritance.Cclass C : B { private int data1; private int data4; public C() { data1 = 5; data4 = 4; } public void GetCData(out int data1, out int data4) { data1 = this.data1; data4 = this.data4; }}

  • DataMemberInheritance.Program.Main (1/2)A a = new A();B b = new B();C c = new C();a.GetAData(out data1, out data2);Debug.Assert(data1 == 1 && data2 == 2);b.GetAData(out data1, out data2);Debug.Assert(data1 == 1 && data2 == 2);b.GetBData(out data3);Debug.Assert(data3 == 3);c.GetAData(out data1, out data2);Debug.Assert(data1 == 1 && data2 == 2);

  • DataMemberInheritance.Program.Main (2/2)c.GetBData(out data3);Debug.Assert(data3 == 3);c.GetCData(out data1, out data4);Debug.Assert(data1 == 5 && data4 == 4);

  • MemberFunctionInheritance.Aclass A { private int data1; private int data2; public A() { data1 = 1; data2 = 2; } public int GetData1() { return data1; } public int GetData2() { return data2; }}

  • MemberFunctionInheritance.Bclass B : A { private int data3; public B() { data3 = 3; } public int Data3 { get { return data3; } }public int GetSum() {return (GetData2() + data3);}}

  • MemberFunctionInheritance.C (1/2)class C : B { private int data1; private int data4; public C() { data1 = 5; data4 = 4; } public new int GetData1() { return data1; }

  • MemberFunctionInheritance.C (2/2)public int GetData4() { return data4; }public int GetAData1() {return base.GetData1();}}

  • MemberFunctionInheritance.Program.Main (1/2)A a = new A();B b = new B();C c = new C();data1 = a.GetData1();data2 = a.GetData2();Debug.Assert(data1 == 1 && data2 == 2);data1 = b.GetData1();data2 = b.GetData2();data3 = b.Data3;Debug.Assert(data1 == 1 && data2 == 2 && data3 == 3);

  • MemberFunctionInheritance.Program.Main (2/2)int sum = b.GetSum();Debug.Assert(sum == 5);data1 = c.GetData1();data2 = c.GetData2();data3 = c.Data3;data4 = c.GetData4();int aAData1 = c.GetAData1();Debug.Assert(data1 == 5 && data2 == 2 && data3 == 3 && data4 == 4 && aAData1 == 1);

  • protectedOCP:-0.1

  • CalculatorInheritance

  • CalculatorInheritance.Program.MainCalculator c = new Calculator();c.Run();AdvancedCalculator ac = new AdvancedCalculator();ac.Run();

  • CalculatorInheritance.Calculatorprotected int register1;protected int register2;protected int display;protected char op;public Calculator() { register1 = 0; register2 = 0; display = 0; op = '+';}

  • CalculatorInheritance.Calculator.Run (1/2)Console.WriteLine("Calculator");while(true) { Console.Write("Turning off? (Y/N): "); answer = char.Parse(Console.ReadLine()); if( answer == 'Y' || answer == 'y' ) break; Console.Write("Enter operand 1: "); register1 = int.Parse(Console.ReadLine()); Console.Write( "Enter operator +, -, *, / "); op = char.Parse(Console.ReadLine()); Console.Write("Enter operand 2: "); register2 = int.Parse(Console.ReadLine());

  • CalculatorInheritance.Calculator.Run (2/2) switch (op) { case '+': Add(); break; case '-': Subtract(); break; . . . . . . default: Console.WriteLine( "Should not see this message. Debug!!!"); break; } Console.WriteLine(display);}

  • CalculatorInheritance.Calculatorprotected void Add() { display = register1 + register2;}protected void Subtract() { display = register1 - register2;}protected void Multiply() { display = register1 * register2;}protected void Divide() { display = register1 / register2;}

  • CalculatorInheritance.AdvancedCalculator (1/3)class AdvancedCalculator : Calculator {public new void Run() { Console.WriteLine("Advanced Calculator"); while(true) { Console.Write("Turning off? (Y/N): "); answer = char.Parse(Console.ReadLine()); if( answer == 'Y' || answer == 'y' ) break; Console.Write("Enter operand 1: "); register1=int.Parse(Console.ReadLine()); Console.Write( "Enter operator +, -, *, /, ^ "); op = char.Parse(Console.ReadLine());

  • CalculatorInheritance.AdvancedCalculator (2/3) Console.Write("Enter operand 2:"); register2=int.Parse(Console.ReadLine()); switch (op) { . . . . . . case '^': Power(); break; default: . . . . . . } Console.WriteLine(display); } }

  • CalculatorInheritance.AdvancedCalculator (3/3) protected void Power() { display = (int) Math.Pow(register1, register2); }}

  • protectedOCP:-0.1

  • SealedClassExample.Parentsealed class Parent { private int data1; public Parent() { data1 = 0; } public int Data1 { get { return data1; } }}

  • SealedClassExample.Childclass Child : Parent // Error!{ private int data2; public Child() { data2 = 0; } public int Data2 { get { return data2; } }}

  • protectedOCP:-0.1

  • UsingConstructorsForInheritance.Program.Main Animal slug = new Animal();Animal tweety = new Animal( "canary" );Primate godzilla = new Primate();Primate human = new Primate( 4 );Human jill = new Human();

  • UsingConstructorsForInheritance.Animalclass Animal { private string species; public Animal() { Console.WriteLine("Animal()"); species = "Animal";}public Animal( string s ) { Console.WriteLine("Animal("+ s +")"); species = s; }}

  • UsingConstructorsForInheritanc.Primateclass Primate : Animal { private int heartCham; public Primate() : base() { Console.WriteLine( "Primate()" );}public Primate( int n ) : base( "Primate" ) { Console.WriteLine("Primate(" + n +")"); heartCham = n;}}

  • UsingConstructorsForInheritanc.Humanclass Human : Primate { public Human() : base( 4 ) { Console.WriteLine( "Human()" );}}

  • Primate human = new Primate( 4 );public Primate( int n ) : base( "Primate" ){ . . .

    }public Animal( string s ){ . . . }

  • UsingConstructorsForInheritance

  • protectedOCP:-0.1

  • -(OCP:Open-Closed Principle)Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification

    *Robert C. Martin, Agile Software Development: Principles, Patterns, and Practices, Pearson Education, 2003

  • OCPViolationExample

  • OCPViolationExample.Program.MainPoint center;center.x = 15;center.y = 20;Point topLeft;topLeft.x = 30;topLeft.y = 40;Shape[] list = { new Circle(2, center), new Rectangle(3, 4, topLeft) };DrawAllShapes(list);

  • OCPViolationExample.Program.DrawAllShapesstatic void DrawAllShapes(Shape[] list) { for (int i = 0; i < list.Length; ++i) { Shape s = list[i]; switch (s.type) { case ShapeType.CIRCLE: DrawCircle((Circle) s); break; case ShapeType.RECTANGLE: DrawRectangle((Rectangle) s); break; } }}

  • OCPViolationExample.Program.DrawCircleDrawRectanglestatic void DrawCircle(Circle c){ Console.WriteLine("Draw a circle");}static void DrawRectangle(Rectangle r){ Console.WriteLine("Draw a rectangle");}

  • OCPViolationExampleclass Shape { public ShapeType type; public Shape(ShapeType t) { type = t; }}class Circle : Shape { private int radius; private Point center; public Circle(int radius, Point center) :base(ShapeType.CIRCLE) { this.radius = radius; this.center = center; }}

  • OCPViolationExample.Rectangleclass Rectangle : Shape{ private int width; private int height; private Point topLeft; public Rectangle(int width, int height, Point topLeft) : base(ShapeType.RECTANGLE) { this.width = width; this.height = height; this.topLeft = topLeft; }}

  • OCPViolationExampleShape()switchShapeenumswitchProgramDraw

  • protectedOCP:-0.1

  • (packaging)(inheritance)(polymorphism)

  • (compile-time binding)(run-time binding)(static binding)(dynamic binding)(virtual)(override)

  • DrawingAllShapes

  • DrawingAllShapes.Program.Main(1/2)Shape[] list = new Shape[2];Point center;center.x = 15;center.y = 20;Point topLeft;topLeft.x = 30;topLeft.y = 40;Circle c = new Circle(2, center);Rectangle r = new Rectangle(3, 4, topLeft);Console.WriteLine(", ");Console.WriteLine("1: , ");Console.WriteLine("2: , ");int ans = int.Parse(Console.ReadLine());

  • DrawingAllShapes.Program.Main(2/2)switch (ans){ case 1: list[0] = c; list[1] = r; break; case 2: list[0] = r; list[1] = c; break; default: . . .}DrawAllShapes(list);

  • DrawingAllShapes.Program.DrawAllShapesstatic void DrawAllShapes(Shape[] list){ int i; for (i = 0; i < list.Length; ++i) { list[i].Draw(); }}

  • DrawingAllShapes.Shape class Shape{ public Shape() { } virtual public void Draw() { }}

  • DrawingAllShapes.Circle class Circle : Shape{ private int radius; private Point center; public Circle(int radius, Point center) { this.radius = radius; this.center = center; } override public void Draw() { Console.WriteLine("Draw a circle"); }}

  • DrawingAllShapes.Rectangle class Rectangle : Shape { private int width; private int height; private Point topLeft; public Rectangle(int width, int height, Point topLeft) { this.width = width; this.height = height; this.topLeft = topLeft; } override public void Draw() { Console.WriteLine("Draw a rectangle"); }}

  • DrawingAllShapescthisrthisc.radiusr.widthc.center.xr.heightc.center.yr.topLeft.xr.topLeft.yCircle.DrawRectangle.Draw

  • DrawingAllShapesTriangle

  • protectedOCP:-0.1

  • NewVsOverride.Program

  • NewVsOverride.Car// Define the base classclass Car{ public virtual void DescribeCar() { System.Console.WriteLine( "Four wheels and an engine."); }}

  • NewVsOverride.ConvertibleCar// Define the derived classesclass ConvertibleCar : Car{ public new virtual void DescribeCar() { base.DescribeCar(); Console.WriteLine("A roof that opens up."); }}

  • NewVsOverride.Minivanclass Minivan : Car{ public override void DescribeCar() { base.DescribeCar(); Console.WriteLine( "Carries seven people."); }}

  • NewVsOverride.Program.Main (1/2)// new and override make no differences hereCar car1 = new Car();car1.DescribeCar();Console.WriteLine("----------");

    ConvertibleCar car2 = new ConvertibleCar();car2.DescribeCar();Console.WriteLine("----------");

    Minivan car3 = new Minivan();car3.DescribeCar();Console.WriteLine("----------");

  • NewVsOverride.Program.Main (2/2)// they are different in polymorphysm Car[] cars = new Car[3];cars[0] = new Car();cars[1] = new ConvertibleCar();cars[2] = new Minivan();foreach (Car vehicle in cars){ Console.WriteLine("Car object: " + vehicle.GetType()); vehicle.DescribeCar(); Console.WriteLine("----------");}

  • : overridePolymorphism ()

    : new

  • NewVsOverride

  • protectedOCP:-0.1

  • BlackJack_0_1

  • BlackJack_0_1.BlackJackTest (1/2)public static bool Scenario1_OK(){ Card[] cards = { new Card(Suit.SPADE, 1), new Card(Suit.HEART, 11), new Card(Suit.DIAMOND, 10) }; Deck deck = new Deck(cards); Player player = new Player(); Dealer dealer = new Dealer();

  • BlackJack_0_1.BlackJackTest (2/2)player.SaveACard(deck.DealACard()); dealer.SaveACard(deck.DealACard()); player.SaveACard(deck.DealACard()); return( player.GetStatus() == Status.BLACK_JACK && dealer.GetStatus() == Status.PASS);}

  • BlackJack_0_1.Game (1/6)const int N_PLAYERS = 2;Deck deck;Player[] players = new Player[N_PLAYERS];public Game(){ players[0] = new Player("Jeng"); players[N_PLAYERS-1] = new Dealer();}

  • BlackJack_0_1.Game (2/6)private void Play() { int i; // for (i = 0; i < N_PLAYERS; ++i) { players[i].SaveACard( deck.DealACard()); players[i].Dump(); }

  • BlackJack_0_1.Game (3/6) // for (i=0; i < N_PLAYERS; ++i) { players[i].SaveACard( deck.DealACard()); players[i].Dump(); }

  • BlackJack_0_1.Game (4/6) // for(i=0; i
  • BlackJack_0_1.Game (5/6) // Player dealer = players[N_PLAYERS-1]; for(i=0; i= players[i].GetTotalPoints()) { Console.WriteLine( dealer.Name + ""+players[i].Name); } else { Console.WriteLine( players[i].Name+""+dealer.Name); } }}

  • BlackJack_0_1.Game (6/6)private bool IsBlackJackOrBurst( Player player) { bool isBlackJack = false; if (player.GetStatus()==Status.BLACK_JACK) { isBlackJack = true; Console.WriteLine(player.Name+ " BlackJack!!!"); } bool isBurst = false; if (player.GetStatus() == Status.BURST){ isBurst = true; Console.WriteLine(player.Name+" !!!"); } return (isBlackJack || isBurst); }

  • BlackJack_0_1.Player (1/5)private Card[] hand = new Card[11];private int nCards;private Status status;private int totalPoints;private string name;public Player(){ nCards = 0; name = "";}

  • BlackJack_0_1.Player (2/5)public Player(string name){ nCards = 0; this.name = name;}public string Name{ get { return name; }}

  • BlackJack_0_1.Player (3/5)virtual public bool WantOneMoreCard(){ Console.Write("? (y/n) "); string answer = Console.ReadLine(); return (answer == "Y" || answer == "y");}

  • BlackJack_0_1.Player (4/5)public void Dump(){ int i; Console.Write(name+" : "); for (i = 0; i < nCards; ++i) { hand[i].Dump(); Console.Write("\t"); if ((i + 1) % 5 == 0) Console.WriteLine(); }

  • BlackJack_0_1.Player (5/5) Console.WriteLine(); Console.WriteLine(name + " : " + totalPoints);}

  • BlackJack_0_1.Dealerclass Dealer : Player { public Dealer() : base("") {} override public bool WantOneMoreCard() { return (base.GetTotalPoints() < 17); }}

  • System.ObjectLSP: LiskovDIP: ISP: *

  • System.ObjectEqualsGetHashCodeGetTypeReferenceEqualsToStringFinalize

  • InheritingObject.Program.MainTest t1 = new Test();Test t2 = new Test();bool isEqual = t1.Equals(t2);Console.WriteLine(t1.ToString());Console.WriteLine("t1 t2 " + isEqual);

  • InheritingObject.Testclass Test{override public string ToString() { return "InheritingObject.Test"; }}

  • Boxing Unboxingint x = 10;Object obj = (Object) x; // boxingobj = 20;int j = (int)obj; // unboxing

  • System.ObjectLSP: LiskovDIP: ISP: *

  • Liskov (LSP: Liskov Substitution Principle)Subtype must be substitutable for their base typesSo1To2TPPo1o2LSPOCP*Robert C. Martin, Agile Software Development: Principles, Patterns, and Practices, Pearson Education, 2003

  • IS-A

  • LSPViolationExample.Rectangle (1/2)class Rectangle{ private int width; private int height; virtual public int Width { set { width = value; } } virtual public int Height { set { height = value; } }

  • LSPViolationExample.Rectangle (2/2) public int Area() { return width * height; }}

  • LSPViolationExample.Squareclass Square : Rectangle{ override public int Width { set { base.Width = value; base.Height = value; } } override public int Height { set { base.Width = value; base.Height = value; } }}

  • LSPViolationExample.Programclass Program{ static void Main(string[] args) { Square s = new Square(); Test(s); } static void Test(Rectangle r) { r.Width = 5; r.Height = 4; Debug.Assert(r.Area() == 20); }}

  • Rectangle.WidthDebug.Assert( (width == value) && (height == old.height));LSP

  • System.ObjectLSP: LiskovDIP: ISP: *

  • AbstractClassExample.Program.Main() double a = 5.0;Square sq = new Square(a);Console.WriteLine("sq" + sq.Area());Circle c = new Circle(a);Console.WriteLine("c" + c.Area());

  • AbstractClassExample.Shapepublic abstract class Shape { private string shape; public Shape(string shape) { this.shape = shape; Console.WriteLine("" + shape); } abstract public double Area();}

  • AbstractClassExample.Squarepublic class Square : Shape{ double a; public Square(double a): base("") { this.a = a; } public override double Area() { return a * a; }}

  • AbstractClassExample.Circlepublic class Circle : Shape{ double r; public Circle(double r): base("") { this.r = r; } public override double Area() { return Math.PI * r * r; }}

  • DrawingAllShapesShapeShape.Draw()

  • System.ObjectLSP: LiskovDIP: ISP: *

  • (DIP: Dependency-Inversion Principle)High-level modules should not depend on low-level modules. Both should depend on abstractions.Abstractions should not depend on details. Details should depend on abstractions.*Robert C. Martin, Agile Software Development: Principles, Patterns, and Practices, Pearson Education, 2003

  • DIP

  • (State Chart)

  • DIPViolationExample.LampStatusButtonStatuspublic enum LampStatus{ OFF = 0, ON = 1}public enum ButtonStatus{ RELEASED = 0, PRESSED = 1}

  • DIPViolationExample.Lamppublic class Lamp { private LampStatus status = LampStatus.OFF; public LampStatus Status { get { return status; } } public void TurnOn() { status = LampStatus.ON; } public void TurnOff() { status = LampStatus.OFF; } }

  • DIPViolationExample.Button (1/2)public class Button{ private ButtonStatus status = ButtonStatus.RELEASED; private Lamp lamp; public Button(Lamp lamp) { this.lamp = lamp; } public ButtonStatus Status { get { return status; } }

  • DIPViolationExample.Button (2/2) public void Press() { if (status == ButtonStatus.RELEASED) { status = ButtonStatus.PRESSED; lamp.TurnOn(); } } public void Release() { if( status == ButtonStatus.PRESSED ){ status = ButtonStatus.RELEASED; lamp.TurnOff(); } }}

  • DIPViolationExample.Program.Main() (1/3)Lamp lamp1 = new Lamp(1);Button button = new Button(lamp1);Random rand = new Random();for (int n = 0; n
  • DIPViolationExample.Program.Main() (2/3) if (rand.Next() % 2 == 1) { if (button.Status == ButtonStatus.PRESSED) { button.Release(); } else { button.Press(); } }

  • DIPViolationExample.Program.Main() (3/3) if (lamp1.Status == LampStatus.OFF) { Console.WriteLine("lamp1 is off"); } else { Console.WriteLine("lamp1 is on"); } Console.WriteLine();}

  • System.ObjectLSP: LiskovDIP: ISP: *

  • UsingInterface.Program.Maindouble a = 5.0;Square sq = new Square(a);Console.WriteLine("sq" + sq.Area());Circle c = new Circle(a);Console.WriteLine("c" + c.Area());

  • UsingInterface.Shapeinterface Shape{ double Area();}

  • UsingInterface.Squarepublic class Square : Shape{ double a; public Square(double a) { this.a = a; } public double Area() { return a * a; }}

  • UsingInterface.Circlepublic class Circle : Shape{ double r; public Circle(double r) { this.r = r; } public double Area() { return Math.PI * r * r; }}

  • vs. (1/2)interface Shape{ double Area();}--------------------------------------------public abstract class Shape { private string shape; public Shape(string shape) { this.shape = shape; Console.WriteLine("" + shape); } abstract public double Area();}

  • vs. (2/2)public class Square : Shape {. . . public double Area() { return a * a; }} --------------------------------------------public class Square : Shape { . . . public override double Area() { return a * a; }}

  • DIP

  • ButtonAndLamppublic interface SwitchableDevice { void TurnOn(); void TurnOff();}public enum LampStatus { OFF = 0, ON = 1}public enum ButtonStatus { RELEASED = 0, PRESSED = 1}

  • ButtonAndLamp.Lamppublic class Lamp : SwitchableDevice { private LampStatus status = LampStatus.OFF; public LampStatus Status { get { return status; } } public void TurnOn() { status = LampStatus.ON; } public void TurnOff() { status = LampStatus.OFF; }}

  • ButtonAndLamp.Button (1/2)public class Button{ private ButtonStatus status = ButtonStatus.RELEASED; private SwitchableDevice device; public Button(SwitchableDevice device) { this.device = device; } public ButtonStatus Status { get { return status; } }

  • ButtonAndLamp.Button (2/2) public void Press() { if (status == ButtonStatus.RELEASED) { status = ButtonStatus.PRESSED; device.TurnOn(); } } public void Release() { if (status == ButtonStatus.PRESSED) { status = ButtonStatus.RELEASED; device.TurnOff(); } }}

  • ButtonAndLampFanButtonFan

  • System.ObjectLSP: LiskovDIP: ISP: *

  • (ISP: Interface-Segregation Principle)Clients should not be forced to depend on methods that they do not use

  • ISP

  • ISPViolationExampleinterface TimerClient { void TimeOut();}interface Door : TimerClient { void Lock(); void Unlock(); bool IsOpen();}enum DoorStatus { CLOSED = 0, OPEN = 1}

  • ISPViolationExample.Timer (1/2)class Timer { private int t; private int timeout; private TimerClient client; public Timer(int timeout, TimerClient client) { this.timeout = timeout; this.client = client; t = 0; }

  • ISPViolationExample.Timer (2/2) public void Advance() { ++t; if (t % timeout == 0) { client.TimeOut(); } }}

  • ISPViolationExample.TimedDoor (1/2)class TimedDoor : Door{ private DoorStatus status = DoorStatus.CLOSED; public bool IsOpen() { return (status == DoorStatus.OPEN); } public void Lock() { if (IsOpen()) status = DoorStatus.CLOSED; } public void Unlock() { if (!IsOpen()) status = DoorStatus.OPEN; }

  • ISPViolationExample.TimedDoor (2/2)public void TimeOut() { Lock(); }}

  • ISPViolationExample.Program.Main (1/2)TimedDoor tDoor = new TimedDoor();int timeout = 10;Timer timer = new Timer(timeout, tDoor);int n;const int N = 20;tDoor.Unlock();for (n = 0; n
  • ISPViolationExample.Program.Main(2/2) if (tDoor.IsOpen()) { Console.WriteLine( "n = " + n + "\t tDoor is open"); } else { Console.WriteLine( "n = " + n + "\t tDoor is closed"); } timer.Advance();}

  • System.ObjectLSP: LiskovDIP: ISP: *

  • MultiInterface

  • MultiInterface.Program.MainFloatplane fp = new Floatplane();fp.Sail();fp.Fly();

  • MultiInterfaceinterface Plane{ void Fly();}

    interface Ship{ void Sail();}

  • MultiInterface.Floatplanepublic class Floatplane : Plane, Ship { public Floatplane() { Console.WriteLine(""); } public void Sail() { Console.WriteLine(""); } public void Fly() { Console.WriteLine(""); }}

  • Clock_RadioClockGetTime()RadioPlayMusic()

  • ISP

  • TimedDoorSimulationinterface TimerClient { void TimeOut();}interface Door { void Lock(); void Unlock(); bool IsOpen();}. . .class TimedDoor : Door, TimerClient{ . . .}

  • System.ObjectLSP: LiskovDIP: ISP: *

  • CastMultiInterfaces

  • CastMultiInterfaces.Program.Maindouble a = 5.0;Square sq = new Square(a);Rhombus rhomb = sq as Rhombus;Console.WriteLine( "sq"+rhomb.Area() );if( sq is Rectangle ) { Rectangle rec = (Rectangle) sq; Console.WriteLine("sq"+rec.Area() );}

  • CastMultiInterfacesinterface Rectangle{ double Area();}interface Rhombus{ double Area();}

  • CastMultiInterfaces.Square (1/2)public class Square : Rectangle, Rhombus{ private double a; private double d; public Square(double a) { this.a = a; d = Math.Sqrt(2.0) * a; }

  • CastMultiInterfaces.Square (2/2)double Rectangle.Area() { return a * a; } double Rhombus.Area() { return 0.5 * d * d; }}