1 / 159

繼承與多型 (Inheritance and Polymorphism)

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

Download Presentation

繼承與多型 (Inheritance and Polymorphism)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 繼承與多型(Inheritance and Polymorphism) 鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所

  2. 綱要 • 繼承 • 修飾語protected • 限制繼承 • 繼承架構下的建構函式呼叫 • OCP:開放-封閉原理 • 多型 • 覆寫與隱藏 • 二十一點模擬程式0.1版

  3. 綱要 • 預設類別System.Object • LSP: Liskov替代性原理 • 抽象類別 • DIP: 依存性反轉原理 • 介面 • ISP: 介面分離原理 • 多重介面 • *多重介面鑄形

  4. 綱要 • 繼承 • 修飾語protected • 限制繼承 • 繼承架構下的建構函式呼叫 • OCP:開放-封閉原理 • 多型 • 覆寫與隱藏 • 二十一點模擬程式0.1版

  5. 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; }

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

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

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

  9. 表示繼承的UML類別圖

  10. A B C 類別繼承之階層關係 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 }

  11. 物件記憶體分配模型 A a = new A(); B b = new B(); C c = new C(); data1 a data2 c data1 data1 b data2 data2 data3 data3 data1 data4

  12. DataMemberInheritance.A class 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; } }

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

  14. DataMemberInheritance.C class 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; } }

  15. 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);

  16. 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);

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

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

  19. 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; }

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

  21. 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);

  22. 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);

  23. 練習 • 實作並測試下列繼承關係

  24. 綱要 • 繼承 • 修飾語protected • 限制繼承 • 繼承架構下的建構函式呼叫 • OCP:開放-封閉原理 • 多型 • 覆寫與隱藏 • 二十一點模擬程式0.1版

  25. CalculatorInheritance類別圖

  26. CalculatorInheritance.Program.Main片段 Calculator c = new Calculator(); c.Run(); AdvancedCalculator ac = new AdvancedCalculator(); ac.Run();

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

  28. 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());

  29. 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); }

  30. CalculatorInheritance.Calculator片段 protected void Add(){ display = register1 + register2; } protected void Subtract(){ display = register1 - register2; } protected void Multiply(){ display = register1 * register2; } protected void Divide(){ display = register1 / register2; }

  31. 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());

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

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

  34. 綱要 • 繼承 • 修飾語protected • 限制繼承 • 繼承架構下的建構函式呼叫 • OCP:開放-封閉原理 • 多型 • 覆寫與隱藏 • 二十一點模擬程式0.1版

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

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

  37. 綱要 • 繼承 • 修飾語protected • 限制繼承 • 繼承架構下的建構函式呼叫 • OCP:開放-封閉原理 • 多型 • 覆寫與隱藏 • 二十一點模擬程式0.1版

  38. 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();

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

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

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

  42. 衍生物件產生流程 Primate human = new Primate( 4 ); public Primate( int n ) : base( "Primate" ) { . . . } public Animal( string s ) { . . . }

  43. 練習 • 利用偵錯器體驗了解程式UsingConstructorsForInheritance

  44. 綱要 • 繼承 • 修飾語protected • 限制繼承 • 繼承架構下的建構函式呼叫 • OCP:開放-封閉原理 • 多型 • 覆寫與隱藏 • 二十一點模擬程式0.1版

  45. 開放-封閉原理(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

  46. 程式OCPViolationExample類別圖

  47. OCPViolationExample.Program.Main片段 Point 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);

  48. OCPViolationExample.Program.DrawAllShapes static 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; } } }

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

  50. OCPViolationExample class 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; } }

More Related