Chương 4: Kế thừa và Đa hình (Inheritance and Polymorphism )

Tìm hiểu mối quan hệ giữa các đối tượng trong thế giới thực Cách thức mô hình hóa các mối quan hệ này trong chương trình

pdf74 trang | Chia sẻ: lylyngoc | Lượt xem: 1576 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Chương 4: Kế thừa và Đa hình (Inheritance and Polymorphism ), để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Chương 4: Kế thừa và Đa hình (Inheritance and Polymorphism ) ThS. Phạm Thanh An Khoa công nghệ thông tin Đại học Ngân hàng Tp. Hồ Chí Minh Nội dung trình bày  Đặc biệt hóa và tổng quát hóa.  Quan hệ kế thừa.  Đa hình.  Lớp trừu tượng.  Các lớp lồng nhau. Mục tiêu Tìm hiểu mối quan hệ giữa các đối tượng trong thế giới thực Cách thức mô hình hóa các mối quan hệ này trong chương trình Đặc biệt hóa và tổng quát hóa  Quan hệ là một (is a) là một sự đặc biệt hóa Động vật có vú Chó Lớp cơ sở (Base class) Lớp dẫn xuất (Derived class) Khái quát hóa (Generalization) Đặc biệt hóa (Specialization) Kế thừa Trong C#, một quan hệ đặc biệt hóa, được cài đặt thông qua kế thừa. Khái niệm kế thừa được sử dụng để khai báo một lớp mới dựa trên lớp đã tồn tại Người Khách hàng Sinh viênCông nhân Kế thừa (tt) Khai bao một lớp kế thừa từ một lớp khác ta sử dụng dấu “:” theo sau là tên lớp được kế thừa. Ví dụ:  Chúng ta đã khai báo lớp người  Khai báo lớp sinh viên kế thừa lớp người public class Sinhvien : Nguoi Kế thừa (tt)  Lớp mới được gọi là lớp dẫn xuất (Derived- Class)  Lớp được kế thừa gọi là lớp cơ sở (base- class)  Một đối tượng của lớp dẫn xuất thì được xem như một đối tượng của lớp cơ sở của nó  Một đối tượng lớp cơ sở không được xem như là một đối tượng của bất kỳ lớp dẫn xuất nào  Mọi lớp trong .Net đều kế thừa từ lớp object (kế thừa không tường minh) Kế thừa (tt) Lưu ý:  Lớp dẫn xuất sẽ kế thừa tất cả các thành phần không là private (non-private) của lớp cơ sở, bao gồm tất cả các phương thức và biến thành viên.  Lớp dẫn xuất không kế thừa phương thức thiết lập ở lớp cơ sở. Ví dụ 1 : kế thừa Animal Cat Ví dụ 2: kế thừa public class Nguoi { private string ten; private string quequan; // etc. public string Ten { get { return ten;} set { ten = value;} } public string quequan { get { return quequan; } set { quequan = value; } } public void Chaohoi(){ MessageBox.show (“Xin chao từ lớp Nguoi”); } } // kết thúc định nghĩa lớp Ví dụ 2: kế thừa (tt) public class Sinhvien : Nguoi { private string sinhvienid; public int lop; public string Sinhvienid { get { return sinhvienid; } set {sinhvienid = value;} } public void lenlop() { MessageBox.show(“Chúc mùng bạn lên lớp”); lop++; } } Sinhvien sv = new Sinhvien(); sv.Ten = “21HT2”; sv.chaohoi(); sv.lenlop(); Ví dụ: kế thừa Ví dụ 3 : Kế thừa using System; namespace vidu2 { class Inherit { static void Main(string[] args) { Square squareObj =new Square(); Rectangle rectObj =new Rectangle(); squareObj.calculateArea(10,20); rectObj.calculateArea(20,20); } } class Shape { public int length; public int breadth; public void calculateArea(int len, int breadth); { } } } class Rectangle:Shape { public Rectangle() { length=0; breadth=0; } public void calculateArea(int len, int breadth) { Console.WriteLine ("Area of a Rectangle is {0}",len*breadth); } } Ví dụ 3: Kế thừa class Square:Shape { public Square() { } public void calculateArea(int side1, int side2) { int area; area = side1*side2; Console.WriteLine ("Area of a Square is {0}",area); } } } Bổ từ truy cập “protected” Bảo vệ các thành phần hay các phương thức chỉ có thể được truy cập:  Trong phạm vi lớp mà các biến, phương thức được khai báo  Lớp dẫn xuất Sử dụng từ khóa protected. Từ khóa base Sử dụng để truy cập đến các thành phần của lớp cơ sở từ trong lớp dẫn xuất Sử dụng để gọi phương thức thiết lập của lớp cơ sở trong phương thức thiết khi tạo ra một thể hiện của lớp dẫn xuất Sử dụng từ khóa base trong một phương thức static sẽ báo lỗi Ví dụ 1: Từ khóa base Ví dụ 2 : Sử dụng từ khóa base using System; public class Window { private int top; private int left; public Window( int top, int left) { this.top = top; this.left = left; } public void DrawWindow() { Console.WriteLine(“Drawing Window at {0}, {1}”, top, left); } } Ví dụ : Sử dụng từ khóa base public class ListBox: Window { private string mListBoxContents; public ListBox(int top, int left, string theContents) : base(top, left) // gọi phương thức thiết lập của lớp cơ sở { mListBoxContents = theContents; } public new void DrawWindow() { base.DrawWindow(); Console.WriteLine(“ ListBox write: {0}”, mListBoxContents); } } Ví dụ : Sử dụng từ khóa base public class Tester { public static void Main() { Window w = new Window(5, 10); w.DrawWindow(); ListBox lb = new ListBox( 20, 10, “Hello world!”); lb.DrawWindow(); } } Phương thức thiết lập lớp dẫn xuất Mặc định, bất kỳ lớp dẫn xuất nào đầu tiên đều gọi phương thức thiết lập mặc định của lớp cơ sở (phương thức thiết lập không có tham số). Gọi tường minh phương thức thiết cơ sở với từ khóa base. Phương thức thiết lập lớp dẫn xuất public class A { public A (int n) { …} …….. } public class B : A { public B (int n) : base (n) { … } …….. } Từ khóa sealed  Trong C#, Một lớp đã cho có chính xác duy nhất lớp cơ sở trực tiếp (Đơn kế thừa)  Từ khóa sealed được sử dụng để khai báo một lớp không cho các lớp khác kế thừa public sealed class A { … } public class B : A //Compiler error { … } Từ khóa new Được sử dụng như một bổ từ Bổ từ new được sử dụng để che dấu một cách tường minh các thành phần được kế thừa từ lớp cơ sở Sẽ có lỗi nếu sử dụng cả new và override trên cùng một phương thức Ví dụ: từ khóa new Từ khóa override  Sử dụng để sửa đổi một phương thức  Một phương thức override cung cấp một cài đặt mới của phương thức lớp cơ sở, phương thức lớp cơ sở phải khai báo là virtual  Mức truy cập của phương thức trong lớp cở sở không thể được thay đổi bởi phương thức override ở lớp kế thừa  new, static, virtual không thể sử dụng cùng với bổ từ override. Ví dụ : sử dụng new using System; public class Base { public static int val = 123; } public class Derv : Base { //new modifier required new public static int val = 456; public static void Main() { //will execute derived class variable Console.WriteLine (val); } } Ghi đè phương thức (Method Overriding)  Để override một phương thức tồn tại của lớp cơ sở:  Khai báo một phương thức mới trong lớp kế thừa với cùng tên.  Thêm tiền tố trước nó là từ khóa new Ví dụ : sử dụng từ khóa new using System; class IntAddition { public void add() { int firstNum =1; int secondNum =2; Console.WriteLine ("The Sum of the two numbers is : {0}", firstNum+secondNum); } } class StringAddition : IntAddition { new public void add() { string firstStr="a"; string secondStr="b"; Console.WriteLine ("The Sum of the two strings is : {0}", firstStr+secondStr); } } class MethodOverride { public static void Main() { StringAddition objStringAddition = new StringAddition(); objStringAddition.add(); } } Ví dụ : sử dụng từ khóa new Ví dụ: using System; class A { public void F() { Console.WriteLine("A.F"); } public virtual void G() { Console.WriteLine("A.G"); } } class B: A { new public void F() { Console.WriteLine("B.F"); } public override void G() { Console.WriteLine("B.G"); } } Ví dụ (tt) class Test { static void Main() { B b = new B(); A a = b; a.F(); b.F(); a.G(); b.G(); } } Output A.F B.F B.G B.G Ví dụ class Derived: Base // version 2b { public override void Foo() { base.Foo(); Console.WriteLine("Derived.Foo"); } } class Base // version 2 { public virtual void Foo() { Console.WriteLine("Base.Foo"); } } Đa hình Ví dụ: using System; class Parent { public int MethodA() { return (MethodB()*MethodC()); } public virtual int MethodB() { return(10); } public int MethodC() { return(20); } } Ví dụ: class Child : Parent { public override int MethodB() { return(30); } } class PolymorphDemo { public static void Main() { Child ObjChild = new Child(); Console.WriteLine("The output is " +ObjChild.MethodA()); } } Đa hình  Polymorphism (Đa hình). Poly có nghĩa là nhiều và morph có nghĩa là hình dạng (form)  Thông qua kế thừa, một đối tượng lớp được sử dụng nhiều hơn 1 kiểu,  nó có thể là kiểu của chính lớp đó,  hay cũng có thể là kiểu lớp cơ sở. Đa hình  Đa hình đề cập đến khả năng có thể sử dụng nhiều dạng của một kiểu mà không quan tâm tới chi tiết.  Đa hình tập trung việc viết một phương thức có thể thao tác trên nhiều đối tượng của nhiều lớp khác nhau.  Đa hình được cài đặt thông qua kế thừa Tạo một phương thức đa hình  Để tạo một phương thức hỗ trợ tính đa hình, chúng ta khai báo phương thức này là virtual trong lớp cơ sở  Các lớp dẫn xuất tự do cài đặt phương thức đa hình này thêm từ khóa override  Lưu ý:  Thuộc tính không có hỗ trợ đa hình  Chỉ có phương thức, sự kiện, Property hỗ trợ đa hình Từ khóa virtual Dùng để định nghĩa một phương thức hỗ trợ đa hình Các lớp dẫn xuất tự do trong việc cài đặt phương thức virtual sử dụng từ khóa override Ví dụ: cài đặt đa hình using System; namespace VirtualMethods { public class Control { protected int top; protected int left; public Control( int top, int left ) { this.top = top; this.left = left; } public virtual void DrawWindow( ) { Console.WriteLine( “Vẽ Control tại {0}, {1}", top, left ); } } // Kết thúc lớp Control Ví dụ: cài đặt đa hình public class ListBox : Control { private string listBoxContents; public ListBox( int top, int left, string contents ): base(top, left) { listBoxContents = contents; } public override void DrawWindow( ) { base.DrawWindow( ); Console.WriteLine( “Viết ra trong lớp listbox:{0}", listBoxContents ); } } Ví dụ: cài đặt đa hình public class Tester { static void Main( ) { Control win = new Control( 1, 2 ); ListBox lb = new ListBox( 3, 4, "Stand alone list box" ); win.DrawWindow( ); lb.DrawWindow( ); Control[] winArray = new Control[3]; winArray[0] = new Control( 1, 2 ); winArray[1] = new ListBox( 3, 4, "List box in array" ); for ( int i = 0; i < 2; i++ ) { winArray[i].DrawWindow( ); } } // end hàm main } //end class Tester } // kết thúc namespace Các điểm ghi nhớ Đa hình là một kiểu overriding thông mình Đa hình quyết định phương thức nào được gọi tại thời điểm thực thi Đa hình yêu cầu phương thức virtual, và đến lượt phương thức virtual lại cần đến overriding Ví dụ: Cài đặt đa hình (tt) abstract public class Shape { ... public vitual void Draw() { Console.WriteLine( “Lop co so”); } ... } public class Circle : Shape { public Circle() { } public override void Draw() { Console.WriteLine("Drawing the Circle"); } Ví dụ: Cài đặt đa hình (tt) public class line : Shape { public line() { } public override void Draw() { Console.WriteLine("Drawing the Line"); } public class Rectangular : Shape { public Rectangular() { } public override void Draw() { Console.WriteLine("Drawing the Rectangular "); } Các lớp trừu tượng Các lớp trừu tượng là các lớp có thể được kế thừa, những không thể tạo ra đối tượng của lớp. C# cho phép tạo ra các lớp trừu tượng bằng cách thêm vào bổ từ “abstract” trong định nghĩa lớp. Một lớp trừu tượng có thể khai báo các phương thức trừu tượng. Các lớp trừu tượng (tt) Phương thức trừu tượng không có cài đặt chỉ có khai báo Các lớp kế thừa từ lớp trừu tượng phải cài đặt phương thức trừu tượng Ví dụ: lớp trừu tượng using System; abstract class BaseClass { public abstract void MethodA(); public void MethodB() { Console.WriteLine ("This is the non abstract method”); } } class DerivedClass : BaseClass { public override void MethodA() { Console.WriteLine ("This is the abstract method overriden in derived class"); } } Ví dụ: Lớp trừu tượng class AbstractDemo { public static void Main() { DerivedClass objDerived = new DerivedClass(); BaseClass objBase = objDerived; objBase.MethodA(); objDerived.MethodB(); } } Gốc của tất cả các lớp: Lớp Object  Tất cả các lớp trong C#, của bất cứ kiểu dữ liệu nào thì cũng được dẫn xuất từ lớp System.Object, bao gồm cả các kiểu dữ liệu giá trị.  Một lớp cơ sở là cha trực tiếp của một lớp dẫn xuất.  Lớp dẫn xuất này cũng có thể làm cơ sở cho các lớp dẫn xuất xa hơn nữa,  Việc dẫn xuất này sẽ tạo ra một cây thừa kế hay một kiến trúc phân cấp. Gốc của tất cả các lớp: Lớp Object String Array ValueType Exception Delegate Class1 Multicast Delegate Class2 Class3 Object Enum1 Structure1Enum Primitive types Boolean Byte Int16 Int32 Int64 Char Single Double Decimal DateTime System-defined types User-defined types Delegate1 TimeSpan Guid Gốc của tất cả các lớp: Lớp Object Các phương thức trong lớp Object Các lớp lồng nhau (Nesting Classes)  Các lớp chứa những thành viên, và những thành viên này có thể là một lớp khác có kiểu do người dùng định nghĩa (user-defined type).  Đôi khi, các lớp được tạo ra chỉ để phục vụ các lớp bên ngoài, và chức năng của các lớp đó như là lớp trợ giúp (helper class).  Chúng ta có thể định nghĩa một lớp trợ giúp bên trong các lớp ngoài (outer class) Các lớp lồng nhau (Nesting Classes)  Các lớp được định nghĩa bên trong gọi là các lớp lồng (nested class), và lớp chứa được gọi đơn giản là lớp ngoài.  Những lớp lồng có khả năng truy cập đến tất cả các thành viên của lớp ngoài.  Một phương thức của lớp lồng có thể truy cập đến biến thành viên private của lớp ngoài.  Lớp lồng bên trong có thể ẩn đối với tất cả các lớp khác, lớp lồng có thể là private cho lớp ngoài. Các lớp lồng nhau (tt)  Nếu lớp lồng bên trong là public (Nested) và được truy cập bên trong phạm vi của lớp ngoài (Outer), khi đó, chúng ta có thể tham chiếu đến lớp Nested theo cách Outer.Nested,  khi đó lớp bên ngoài hành động ít nhiều giống như một namespace  Thông thường, các lớp lồng hành động như là các lớp trợ giúp cho lớp chứa, và không được thiết kế cho thế giới bên ngoài. Ví dụ: Cài đặt lớp lồng using System; namespace NestedClasses { public class Fraction { private int numerator; private int denominator; public Fraction( int numerator, int denominator) { this.numerator = numerator; this.denominator = denominator; } public override string ToString() { return String.Format( "{0}/{1}", numerator, denominator ); } Ví dụ: Cài đặt lớp lồng internal class FractionArtist { public void Draw( Fraction f ) { Console.WriteLine( "Drawing the numerator: {0}", f.numerator ); Console.WriteLine( "Drawing the denominator: {0}", f.denominator ); } } } Ví dụ: Cài đặt lớp lồng public class Tester { static void Main( ) { Fraction f1 = new Fraction( 3, 4 ); Console.WriteLine( "f1: {0}", f1.ToString( ) ); Fraction.FractionArtist fa = new Fraction.FractionArtist(); fa.Draw( f1 ); } } } Ví dụ: Ví dụ: Polygon Style Point Ví dụ : Car Ví dụ (tt) public class Car { // Aggregation uses instance of class outside of this class protected Door FrontRight; protected Door FrontLeft; protected Door RearRight; protected Door RearLeft; // inner class used to create objects // that are intrinsically linked to the class car protected class Engine { public int horsePower; } protected class Battery { public int voltage; } Ví dụ (tt) //Composition uses instances of objects of inner classes protected Engine TheEngine; protected Engine The Battery; public Car () { TheEngine = new Engine (); TheBattery = new Battery (); } } // kết thúc lớp Car public class Door { public int position; } Interface  Trong một chương trình lớn, việc thiết kế luôn được đặt lên hàng đầu  Việc thiết kế liên quan đến việc thiết kế các lớp, các thuộc tính, các phương thức của lớp  Rất là hữu ích khi chúng ta phân tách được giao diện của lớp và cài đặt lớp  Giao diện của lớp là các thành phần có thể truy cập bởi người sử dụng lớp, có nghĩa là các thành phần public.  Các thành phần public là cách duy nhất để các đoạn code bên ngoài lớp tương tác với các đối tượng của lớp Interface (tt) public interface IFile { int delFile(); void disFile(); } public class MyFile : IFile { public int delFile() { System.Console.WriteLine ("DelFile Implementation!"); return(0); } public void disFile() { System.Console.WriteLine ("DisFile Implementation!"); } } Interface (tt)  Interface thường được xem như các lớp trừu tượng tinh khiết  Một định nghĩa interface, khai báo các phương thức, các thuộc tính, events sẽ được cài đặt bởi một số lớp.  Trong khai báo interface chỉ có duy nhất tiêu đề, không có bất kỳ cài đặt nào  Các lớp cài đặt Interface phải cài đặt các thành phần được khai báo trong Interface Ví dụ public interface IFile { int delFile(); void disFile(); } public class BaseforInterface { public void open() { System.Console.WriteLine ("This is the open method of BaseforInterface"); } } Ví dụ (tt) public class MyFile : BaseforInterface, IFile { public int delFile() { System.Console.WriteLine ("DelFile Implementation!"); return(0); } public void disFile() { System.Console.WriteLine ("DisFile Implementation!"); } } Interface (tt) Một lớp có thể kế thừa duy nhất 1 lớp, và có thể cài đặt nhiều interface public interface IFileTwo { void applySecondInterface(); } Interface (tt) public class MyFile : BaseforInterface, IFile, IFileTwo { public int delFile() { System.Console.WriteLine ("DelFile Implementation!"); return(0); } public void disFile() { System.Console.WriteLine ("DisFile Implementation!"); } public void applySecondInterface() { System.Console.WriteLine ("ApplySecondInterface Implementation!"); } } Cài đặt Interface tường minh public interface IFile { int delFile(); void disFile(); } public interface IFileTwo { void applySecondInterface(); void disFile(); }  Sử dụng khi hai phương thức cùng chung một tên ở trong 2 interfaces. Cài đặt Interface tường minh (tt) public class MyFile : BaseforInterface, IFile, IFileTwo {... void IFile.disFile() { System.Console.WriteLine ("IFile Implementation of DisFile"); } void IFileTwo.disFile() { System.Console.WriteLine ("IFileTwo Implementation of DisFile"); }.. } Q&A
Tài liệu liên quan