[Selenium C#] Bài 3: C# hướng đối tượng (OOP) | Anh Tester

Tóm Tắt

TÍNH KẾ THỪA

Tính thừa kế, tính đóng gói, tính đa hình, tính trừ tượng trong C #Lập trình hướng đối tượng có hai đặc trưng cơ bản :

  • Đóng gói dữ liệu, được thể hiện bằng cách dùng khái niệm lớp để biểu diễn đối tượng với các thuộc tính private, chỉ cho phép bên ngoài truy nhập vào thông qua các phương thức get/set. 
  • Dùng lại mã, thể hiện bằng việc thừa kế giữa các lớp. Việc thừa kế cho phép các lớp thừa kế (gọi là lớp dẫn xuất) sử dụng lại các phương thức đã được định nghĩa trong các lớp gốc (gọi là lớp cơ sở). 

 

Khai báo thừa kế

Cú pháp khai báo một lớp kế thừa từ một lớp khác như sau: 

class : { 
…  // Khai báo các thành phần lớp 
}; 

Ví dụ về đơn kế thừa C #: Kế thừa các trường

Khi một lớp kế thừa một lớp khác, nó được gọi là đơn thừa kế. Chúng ta hãy xem ví dụ về đơn thừa kế cấp chỉ kế thừa các trường chỉ đọc.

using System;  
   public class Employee  
    {  
       public float salary = 40000;  
   }  
   public class Programmer: Employee  
   {  
       public float bonus = 10000;  
   }  
   class TestInheritance{  
       public static void Main(string[] args)  
        {  
            Programmer p1 = new Programmer();  
  
            Console.WriteLine("Salary: " + p1.salary);  
            Console.WriteLine("Bonus: " + p1.bonus);  
  
        }  
    }  

Kết quả:

Salary: 40000
Bonus: 10000

Trong ví dụ trên, Employee là lớp cơ sở còn Programmer là lớp dẫn xuất .

Ví dụ đơn kế thừa cấp: Phương thức kế thừa

Chúng ta hãy xem một ví dụ khác về kế thừa trong C # chỉ kế thừa các phương thức.

using System;  
   public class Animal  
    {  
       public void eat() { Console.WriteLine("Eating..."); }  
   }  
   public class Dog: Animal  
   {  
       public void bark() { Console.WriteLine("Barking..."); }  
   }  
   class TestInheritance2{  
       public static void Main(string[] args)  
        {  
            Dog d1 = new Dog();  
            d1.eat();  
            d1.bark();  
        }  
    }  

Kết quả :

Eating...
Barking...

Ví dụ về đa kế thừa

Khi một lớp thừa kế một lớp khác được thừa kế bởi một lớp khác, nó được gọi là đa thừa kế trong C #. Kế thừa là bắc cầu nên lớp dẫn xuất ở đầu cuối có được toàn bộ những thành viên của toàn bộ những lớp cơ sở của nó .
Hãy xem ví dụ về đa thừa kế trong C # .

using System;  
   public class Animal  
    {  
       public void eat() { Console.WriteLine("Eating..."); }  
   }  
   public class Dog: Animal  
   {  
       public void bark() { Console.WriteLine("Barking..."); }  
   }  
   public class BabyDog : Dog  
   {  
       public void weep() { Console.WriteLine("Weeping..."); }  
   }  
   class TestInheritance2{  
       public static void Main(string[] args)  
        {  
            BabyDog d1 = new BabyDog();  
            d1.eat();  
            d1.bark();  
            d1.weep();  
        }  
    }  

Kết quả :

Eating...
Barking...
Weeping...

Lưu ý: Trong C# không hỗ trợ tại một thời điểm không được thừa kế một lúc nhiều lớp.

C # Aggregation ( Mối quan hệ HAS-A )

Trong C #, aggregation là một một mối quan hệ trong đó một lớp định nghĩa một lớp khác là bất kể tham chiếu đến một đối tượng nào đó. Đó là một cách khác để sử dụng lại lớp. Đó là một hình thức link đại diện thay mặt cho mối quan hệ HAS-A ( có một ) .
Ví dụ :

Chúng ta hãy xem một ví dụ về tập hợp trong đó lớp Employee có tham chiếu của lớp Address là thành viên dữ liệu. Theo cách đó, nó có thể sử dụng lại các thành viên của lớp Address.

using System;  
public class Address  
{  
    public string addressLine, city, state;  
    public Address(string addressLine, string city, string state)  
    {  
        this.addressLine = addressLine;  
        this.city = city;  
        this.state = state;  
    }  
}  
   public class Employee  
    {  
       public int id;  
       public string name;  
       public Address address;//Employee HAS-A Address  
       public Employee(int id, string name, Address address)  
       {  
           this.id = id;  
           this.name = name;  
           this.address = address;  
       }  
       public void display()  
       {  
           Console.WriteLine(id + " " + name + " " +   
             address.addressLine + " " + address.city + " " + address.state);  
       }  
   }  
   public class TestAggregation  
   {  
        public static void Main(string[] args)  
        {  
            Address a1=new Address("G-13, Sec-3","Noida","UP");  
            Employee e1 = new Employee(1,"Sonoo",a1);  
            e1.display();  
        }  
    }  

Kết quả :

1 Sonoo G-13 Sec-3 Noida UP​

Tính đóng gói ( encapsulation ) trong C #

Tính đóng gói ( encapsulation ) ” đóng gói ” thuộc tính và phương pháp của đối tượng ( hoặc lớp ) trải qua việc số lượng giới hạn quyền truy vấn ( hoặc đổi khác ) giá trị của thuộc tính hoặc quyền gọi phương pháp. Nói cách khác tính đóng gói được cho phép trấn áp quyền truy vấn ( và biến hóa ) giá trị của thuộc tính hoặc quyền gọi phương pháp của đối tượng ( hoặc lớp ) và đối tượng ( hoặc lớp ) con .
Một lớp được đóng gói rất đầy đủ có những hàm getter và setter được sử dụng để đọc và ghi tài liệu. Lớp này không được cho phép truy vấn tài liệu trực tiếp .
Ở đây, tất cả chúng ta đang tạo một ví dụ trong đó tất cả chúng ta có một lớp đóng gói những thuộc tính và cung ứng những hàm getter và setter .

Ví dụ:

namespace AccessSpecifiers  
{  
    class Student  
    {  
        // Creating setter and getter for each property  
        public string ID { get; set; }  
        public string Name { get; set; }  
        public string Email { get; set; }  
    }  
}  
using System;  
namespace AccessSpecifiers  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Student student = new Student();  
            // Setting values to the properties  
            student.ID = "101";  
            student.Name = "Mohan Ram";  
            student.Email = "[email protected]";  
            // getting values  
            Console.WriteLine("ID = "+student.ID);  
            Console.WriteLine("Name = "+student.Name);  
            Console.WriteLine("Email = "+student.Email);  
        }  
    }  
}  

Kết quả:

ID = 101
Name = Mohan Ram
Email = [email protected]

TÍNH ĐA HÌNH

Nạp chồng ( Overloading ) trong C #

Trong một lớp, ta hoàn toàn có thể tạo ra nhiều hàm với cùng một tên gọi nhưng khác nhau những tài liệu nguồn vào hoặc tham số, đó gọi là nạp chồng. Trong C + +, Chúng ta hoàn toàn có thể nạp chồng :

  • Phương thức (methods),
  • Phương thức thiết lập(constructors), 
  • indexed properties

Các kiểu quá nạp chồng trong C # :

  • Nạp chồng phương thức
  • Nạp chồng các toán tử 


Nạp chồng phương thức

Trong một lớp, ta có thể tạo ra nhiều hàm với cùng một tên gọi nhưng khác nhau các dữ liệu đầu vào hoặc tham số, đó gọi là nạp chồng phương thức.
Lới ích của việc quá tải phương thức là chúng ta có thể khai báo cùng một tên phương thức trong cùng chương trình, không cần phải khai báo tên khác cho cùng một hành đông.

Ví dụ nạp chồng phương thức C#

Ví dụ trong lớp Cal sau có hai phương pháp add nhưng khác nhau về tham số :

using System;  
public class Cal{  
    public static int add(int a,int b){  
        return a + b;  
    }  
    public static int add(int a, int b, int c)  
    {  
        return a + b + c;  
    }  
}  
public class TestMemberOverloading  
{  
    public static void Main()  
    {  
        Console.WriteLine(Cal.add(12, 23));  
        Console.WriteLine(Cal.add(12, 23, 25));  
    }  
}  

Kết quả :

35
60


Ví dụ về nạp chồng: Bằng cách thay đổi kiểu dữ liệu của các tham số

Chúng ta hãy xem một ví dụ khác về nạp chồng phương pháp trong đó tất cả chúng ta sẽ đổi khác kiểu tài liệu của đối số .

using System;  
public class Cal{  
    public static int add(int a, int b){  
        return a + b;  
    }  
    public static float add(float a, float b)  
    {  
        return a + b;  
    }  
}  
public class TestMemberOverloading  
{  
    public static void Main()  
    {  
        Console.WriteLine(Cal.add(12, 23));  
        Console.WriteLine(Cal.add(12.4f,21.3f));  
    }  
}  

Kết quả :

35
33.7

Phương thức Ghi đè ( Overriding ) trong C #

Trong C #, nếu lớp dẫn xuất định nghĩa cùng một phương pháp đã được định nghĩa trong lớp cơ sở, nó được gọi là phương pháp ghi đè. Phương thức ghi đè được sử dụng để đạt được tính đa hìn. Phương thức ghi đè được cho phép bạn phân phối việc triển khai đơn cử công dụng đã được lớp cơ sở của nó phân phối .

Phương thức ghi đè thường được sử dụng trong phương thức ở lớp con.
Một số quy tắc sử dụng phương thức ghi đè:

  • Các phương thức static thì không ghi đè nhưng được mô tả lại.
  • Các phương thức không kế thừa sẽ không được overriden (hiển nhiên).

Để thực hiện ghi đè phương thức trong C #, bạn cần sử dụng từ virtual với phương thức lớp cơ sở và từ khóa override cho phương thức lớp dẫn xuất.

Ví dụ sau chúng ta ghi đè phương thức eat()

Chúng ta hãy xem một ví dụ đơn giản về phương thức ghi đè trong C#. Trong ví dụ này, chúng ta đang ghi đè phương thức eat () bằng từ khóa override.

using System;  
public class Animal{  
    public virtual void eat(){  
        Console.WriteLine("Eating...");  
    }  
}  
public class Dog: Animal  
{  
    public override void eat()  
    {  
        Console.WriteLine("Eating bread...");  
    }  
}  
public class TestOverriding  
{  
    public static void Main()  
    {  
        Dog d = new Dog();  
        d.eat();  
    }  
}  

Kết quả :

Eating bread...​

Từ khóa Base trong C#

Trong C #, từ khóa base được sử dụng để truy cập các trường, hàm khởi tạo và phương thức của lớp cơ sở.
Bạn chỉ có thể sử dụng từ khóa base trong phương thức, hàm khởi tạo hoặc hàm truy cập thuộc tính của đối tượng. Bạn không thể sử dụng nó trong phương thức tĩnh.

Ví dụ về từ khóa base: truy cập trường của lớp cơ sở

Chúng ta hoàn toàn có thể sử dụng từ khóa base để truy vấn vào những trường của lớp cơ sở trong lớp dẫn xuất. Nó rất có ích nếu những lớp cơ sở và những lớp dẫn xuất có cùng những trường. Nếu lớp dẫn xuất không định nghĩa cùng một trường, thì không cần sử dụng từ khóa cơ sở. Trường trong lớp cơ sở hoàn toàn có thể được truy vấn trực tiếp bởi lớp dẫn xuất .

using System;  
public class Animal{  
    public string color = "white";  
}  
public class Dog: Animal  
{  
    string color = "black";  
    public void showColor()  
    {  
        Console.WriteLine(base.color);  
        Console.WriteLine(color);  
    }  
      
}  
public class TestBase  
{  
    public static void Main()  
    {  
        Dog d = new Dog();  
        d.showColor();  
    }  
}  

Kết quả:

white
black

Đa hình ( Polymorphism ) trong C #

Đa hình là thuật ngữ được dùng trong hướng đối tượng dùng để chỉ việc ứng xử khác nhau của những đối tượng trong những lớp kế thừa từ một lớp cơ sở khi một phương pháp chung được gọi. Tính đa hình được sử dụng trong trường hợp một phương pháp chung được sử dụng trong nhiều lớp dẫn xuất nhưng ứng với mỗi lớp dẫn xuất đơn cử thì phương pháp này có những ứng xử khác nhau. Để triển khai được tính đa hình, phương pháp ở lớp cơ sở phải được miêu tả ở dạng ảo ( virtual ) và phương pháp đó ở lớp dẫn xuất phải được ghi đè ( override ). Override là thuật ngữ được dùng để chỉ việc lớp dẫn xuất đặc tả lại phương pháp ở lớp cơ sở. Ví dụ sau trình bày việc triển khai tính năng đa hình khi thiết kế xây dựng một lớp cơ sở và hai lớp dẫn xuất .

Có hai loại đa hình trong C #: đa hình thời gian biên dịch và đa hình thời gian chạy.
Đa hình thời gian biên dịch bằng cách nạp chồng phương thức và nạp chồng toán tử trong C #. Nó còn được gọi là ràng buộc tĩnh hoặc ràng buộc sớm.
Đa hình thời gian chạy bằng phương pháp ghi đè, còn được gọi là liên kết động hoặc liên kết muộn.

Ví dụ 1 : đa hình thời hạn chạy C #

Chúng ta hãy xem một ví dụ đơn giản về đa hình thời gian chạy trong C#.

using System;  
public class Animal{  
    public virtual void eat(){  
        Console.WriteLine("eating...");  
    }  
}  
public class Dog: Animal  
{  
    public override void eat()  
    {  
        Console.WriteLine("eating bread...");  
    }  
      
}  
public class TestPolymorphism  
{  
    public static void Main()  
    {  
        Animal a= new Dog();  
        a.eat();  
    }  
}  

Kết quả :

eating bread...

Ví dụ 2 : Đa hình thời hạn chạy C #

Chúng ta hãy xem một ví dụ khác về đa hình thời gian chạy trong C#, ở đây có hai lớp dẫn xuất.

using System;  
public class Shape{  
    public virtual void draw(){  
        Console.WriteLine("drawing...");  
    }  
}  
public class Rectangle: Shape  
{  
    public override void draw()  
    {  
        Console.WriteLine("drawing rectangle...");  
    }  
      
}  
public class Circle : Shape  
{  
    public override void draw()  
    {  
        Console.WriteLine("drawing circle...");  
    }  
  
}  
public class TestPolymorphism  
{  
    public static void Main()  
    {  
        Shape s;  
        s = new Shape();  
        s.draw();  
        s = new Rectangle();  
        s.draw();  
        s = new Circle();  
        s.draw();  
  
    }  
}  

Kết quả :

drawing...
drawing rectangle...
drawing circle...

Đa hình trong lúc chạy với những thành viên tài liệu

Đa hình thời gian chạy không thể đạt được bởi các thành viên dữ liệu trong C#. Chúng ta hãy xem một ví dụ: Chúng ta đang truy cập vào trường bằng biến tham chiếu đến đối tượng của lớp dẫn xuất.

using System;  
public class Animal{  
    public string color = "white";  
  
}  
public class Dog: Animal  
{  
    public string color = "black";  
}  
public class TestSealed  
{  
    public static void Main()  
    {  
        Animal d = new Dog();  
        Console.WriteLine(d.color);  
    
    }  
}  

Kết quả :

white​

Lớp niêm phong ( Sealed class )

  • Từ khóa sealed được sử dụng để biểu thị khi khai báo một class nhằm ngăn ngừa sự dẫn xuất từ một class, điều này cũng giống như việc ngăn cấm một class nào đó có class con.
  • Một class sealed cũng không thể là một class trừu tượng.
  • Các structs trong C# được ngầm định sealed. Do vậy, chúng không thể được thừa kế


Cú pháp:

 sealed class tên_class
{
// Các thành viên của class trừu tượng.
}

Lưu ý : Các kiểu cấu trúc được niêm phong ngầm do đó chúng không hề được thừa kế .

Lớp niêm phong C # không hề được dẫn xuất bởi bất kể lớp nào .

Chúng ta hãy xem một ví dụ về lớp niêm phong trong C#.

using System;  
sealed public class Animal{  
    public void eat() { Console.WriteLine("eating..."); }  
}  
public class Dog: Animal  
{  
    public void bark() { Console.WriteLine("barking..."); }  
}  
public class TestSealed  
{  
    public static void Main()  
    {  
        Dog d = new Dog();  
        d.eat();  
        d.bark();  
  
  
    }  
}  

Kết quả :

Compile Time Error: 'Dog': cannot derive from sealed type 'Animal'

Phương pháp niêm phong C#

Phương pháp niêm phong trong C# không thể được ghi đè. Nó phải được sử dụng với từ khóa ghi đè trong phương thức.

Chúng ta hãy xem một ví dụ về chiêu thức niêm phong trong C # .

using System;  
public class Animal{  
    public virtual void eat() { Console.WriteLine("eating..."); }  
    public virtual void run() { Console.WriteLine("running..."); }  
  
}  
public class Dog: Animal  
{  
    public override void eat() { Console.WriteLine("eating bread..."); }  
    public sealed override void run() {   // Phương thức niêm phong
    Console.WriteLine("running very fast...");   
    }  
}  
public class BabyDog : Dog  
{  
    public override void eat() { Console.WriteLine("eating biscuits..."); }  
    public override void run() { Console.WriteLine("running slowly..."); }  
}  
public class TestSealed  
{  
    public static void Main()  
    {  
        BabyDog d = new BabyDog();  
        d.eat();  
        d.run();  
    }  
}  

Kết quả :

Compile Time Error: 'BabyDog.run()': cannot override inherited member 'Dog.run()' because it is sealed

Lưu ý : Các biến cục bộ không hề được niêm phong .

using System;  
public class TestSealed  
{  
    public static void Main()  
    {  
        sealed int x = 10;  
        x++;  
        Console.WriteLine(x);  
    }  
}  

Kết quả :

Compile Time Error: Invalid expression term 'sealed'

Lớp trừu tượng (Abstract Class) trong C#

Lớp trừu tượng đơn thuần được xem như một class cha cho tổng thể những Class có cùng thực chất. Do đó mỗi lớp dẫn xuất ( lớp con ) chỉ hoàn toàn có thể kế thừa từ một lớp trừu tượng. Bên cạnh đó nó không được cho phép tạo instance, nghĩa là sẽ không hề tạo được những đối tượng thuộc lớp đó .
Lớp Abstract sẽ định nghĩa toàn bộ những phương pháp để những lớp dẫn xuất khi kế thừa từ nó phải định nghĩa lại ( Override ) – Tính đa hình trong lập trình hướng đối tượng OOP. Do đó kể lớp dẫn xuất hoàn toàn có thể thừa kế và định nghĩa lại thì những toàn bộ những phương pháp trong lớp Abstract bắt buộc phải sử dụng từ khóa truy vấn là public hoặc protected. Không thể sử dụng từ khóa private. Lớp Abstract hoàn toàn có thể có thuộc tính nhưng ko được sử dụng từ khóa abstract cho thuộc tính. Mặt khác, Abstract class không được cho phép bạn khởi tạo một object từ nó được .
Trừu tượng hoàn toàn có thể làm bằng hai cách :

    1. Lớp trừu tượng (Abstract class)
    2. Giao diện (Interface)

Cả lớp trừu tượng và giao diện đều hoàn toàn có thể có những phương pháp trừu tượng thiết yếu cho sự trừu tượng hóa .

Phương pháp trừu tượng

Một phương thức được khai báo là trừu tượng và không có phần thân được gọi là phương thức trừu tượng. Nó chỉ có thể được khai báo bên trong lớp trừu tượng. Việc thực hiện của nó phải được cung cấp bởi các lớp dẫn xuất.

Ví dụ:

public abstract void draw();  

Lưu ý : Một phương thức trừu tượng trong C # bên trong là một phương thức ảo để nó có thể bị ghi đè bởi lớp dẫn xuất.


Lớp trừu tượng C#

Trong C #, lớp trừu tượng là một lớp được khai báo là trừu tượng. Nó hoàn toàn có thể có những giải pháp trừu tượng hoặc không trừu tượng. Nó không hề được khởi tạo. Việc triển khai của nó phải được cung ứng bởi những lớp dẫn xuất. Ở đây, lớp dẫn xuất buộc phải thực thi toàn bộ những phương pháp trừu tượng .
Chúng ta hãy xem một ví dụ về lớp trừu tượng trong C # có một phương pháp trừu tượng draw ( ). Việc thực thi của nó bởi những lớp dẫn xuất : Hình chữ nhật và Vòng tròn. Cả hai lớp có cách thực thi khác nhau .

using System;  
public abstract class Shape  
{  
    public abstract void draw();  
}  
public class Rectangle : Shape  
{  
    public override void draw()  
    {  
        Console.WriteLine("drawing rectangle...");  
    }  
}  
public class Circle : Shape  
{  
    public override void draw()  
    {  
        Console.WriteLine("drawing circle...");  
    }  
}  
public class TestAbstract  
{  
    public static void Main()  
    {  
        Shape s;  
        s = new Rectangle();  
        s.draw();  
        s = new Circle();  
        s.draw();  
    }  
}  

Kết quả :

drawing ractangle...
drawing circle...

Giao diện ( interface ) trong C #

Khi nhìn qua ta thấy Interface rất giống với Abstract trong C # ? Nhưng về thực chất bên trong trọn vẹn khác nhau. Interface không phải là một lớp đơn cử mà là một khuôn mẫu để cho một đối tượng implement nó, và đương nhiên là ta không hề tạo một biến Interface. Ngược lại lớp Abstract là một lớp đơn cử, có rất đầy đủ những đặc thù của một đối tượng, hoàn toàn có thể gọi, định nghĩa những hàm trong nó. Đối với hằng số ở lớp implement không được định nghĩa lại .

Cú pháp:

 interface [interfaceName]

Một số điểm cần chú ý quan tâm khi thao tác với interface .

  • Lớp kế thừa không được định nghĩa lại hằng số đã được định nghĩa trong interface.
  • Định nghĩ đúng các hàm của lớp kế thừa như trong interface.
  • Định nghĩa đúng mức truy cập các hàm của lớp kế thừa như trong interface.
  • Một interface chứa các hành vi(Action) mà một class(lớp) triển khai.
  • Một interface có thể bao gồm bất cứ lượng phương thức nào.
  • Bạn không thể khởi tạo một interface.
  • Một interface không chứa bất cứ hàm contructor nào.
  • Tất cả các phương thức của interface đều là abstract.
  • Một interface không thể chứa một trường nào trừ các trường vừa static và final.
  • Một interface không thể kế thừa từ lớp, nó được triển khai bởi một lớp.
  • Một interface có thể kế thừa từ nhiều interface khác.


Ví dụ giao diện C#

Hãy xem ví dụ về giao diện trong C # có phương pháp draw ( ). Việc triển khai của nó được phân phối bởi hai lớp : Rectangle và Circle .

using System;  
public interface Drawable  
{  
    void draw();  
}  
public class Rectangle : Drawable  
{  
    public void draw()  
    {  
        Console.WriteLine("drawing rectangle...");  
    }  
}  
public class Circle : Drawable  
{  
    public void draw()  
    {  
        Console.WriteLine("drawing circle...");  
    }  
}  
public class TestInterface  
{  
    public static void Main()  
    {  
        Drawable d;  
        d = new Rectangle();  
        d.draw();  
        d = new Circle();  
        d.draw();  
    }  
}  

Kết quả:

drawing ractangle...
drawing circle...

Lưu ý: Mặc định các phương thức giao diện là public và trừu tượng. Chúng ta không thể sử dụng từ khóa public và abstract cho phương thức giao diện

using System;  
public interface Drawable  
{  
    public abstract void draw();//Compile Time Error  
}