Tài liệu

Selenium C#: Bài 3 - Lập trình hướng đối tượng (OOP)

Huy Erick

Trong bài viết này, chúng ta sẽ tìm hiểu về lập trình hướng đối tượng (OOP) trong Selenium C#. Tính kế thừa Lập trình hướng đối tượng có hai đặc trưng cơ bản: Đóng gói...

Trong bài viết này, chúng ta sẽ tìm hiểu về lập trình hướng đối tượng (OOP) trong Selenium C#.

Tính kế thừa

Lập trình hướng đối tượng có hai đặc trưng cơ bản:

  • Đóng gói dữ liệu: Sử 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 truy cập thông qua các phương thức get/set.
  • Dùng lại mã: Thừa kế giữa các lớp cho phép các 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 cơ sở.

Để khai báo kế thừa, chúng ta sử dụng cú pháp sau:

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

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

Khi một lớp kế thừa một lớp khác, nó được gọi là đơn kế thừa. Dưới đây là ví dụ về đơn kế thừa 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, lớp Employee là lớp cơ sở, trong khi Programmer là lớp dẫn xuất.

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

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 kế thừa một lớp khác được kế thừa bởi một lớp khác, nó được gọi là đa kế thừa. Kế thừa là bắc cầu nên lớp dẫn xuất cuối cùng có được tất cả các thành viên của tất cả các lớp cơ sở của nó.

Dưới đây là ví dụ về đa kế thừa 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ợ đa kế thừa đồng thời từ nhiều lớp.

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

Trong C#, aggregation là một mối quan hệ trong đó một lớp định nghĩa một lớp khác là một thuộc tính của nó. Đây là một cách khác để sử dụng lại lớp. Đây là một hình thức liên kết đại diện 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ó một thuộc tính là Address. Theo cách này, Employee 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 "đóng gói" thuộc tính và phương thức của đối tượng thông qua việc giới hạn quyền truy cập và thay đổi giá trị của thuộc tính hoặc gọi phương thức. Tính đóng gói cho phép kiểm soát quyền truy cập và thay đổi giá trị của thuộc tính hoặc gọi phương thức của đối tượng và đối tượng con.

Một lớp được đóng gói đầy đủ cung cấp các getter và setter để đọc và ghi dữ liệu. Lớp này không cho phép truy cập dữ liệu trực tiếp.

Ở đây, chúng ta tạo một ví dụ trong đó chúng ta có một lớp đóng gói các thuộc tính và cung cấp các getter và setter.

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 = "mohan@example.com";              // 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 = mohan@example.com

Tính đa hình (Polymorphism) trong C

Đa hình là thuật ngữ được dùng trong lập trình hướng đối tượng để chỉ việc ứng xử khác nhau của các đối tượng trong những lớp kế thừa từ một lớp cơ sở khi một phương thức chung được gọi. Đa hình cho phép các đối tượng trong cùng một chương trình thực hiện một hành động một cách khác nhau.

Nạp chồng (Overloading)

Trong C#, chúng ta có thể nạp chồng phương thức và toán tử. Nạp chồng phương thức cho phép chúng ta khai báo cùng một tên phương thức trong cùng một chương trình mà không cần khai báo tên khác.

Ví dụ: Nạp chồng phương thức

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ụ: Nạp chồng phương thức bằng cách thay đổi kiểu dữ liệu của các tham 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)

Khi một lớp dẫn xuất định nghĩa lại một phương thức đã được định nghĩa trong lớp cơ sở, nó được gọi là phương thức ghi đè. Phương thức ghi đè cho phép bạn tuỳ chỉnh việc thực hiện của phương thức đã được định nghĩa trong lớp cơ sở.

Để thực hiện ghi đè phương thức trong C#, bạn cần sử dụng từ khóa 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ụ: Ghi đè phương thứ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 TestOverriding {     public static void Main()     {         Dog d = new Dog();         d.eat();     } }

Kết quả:

Eating bread...

Từ khóa Base

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ụ: Truy cập trường của lớp cơ sở

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 lúc chạy với các thành viên dữ liệu

Đa hình thời gian chạy không áp dụng cho các thành viên dữ liệu trong C#. Dưới đây là một ví dụ khi chúng ta 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 để ngăn ngừa việc kế thừa từ một lớp, cũng giống như việc ngăn cấm một lớp có lớp con.
  • Một lớp niêm phong không thể là một lớp trừu tượng.
  • Các struct trong C# mặc định là niêm phong, vì vậy chúng không thể được kế thừa.

Ví dụ: Lớp niêm phong

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'

Ví dụ: Phương thức niêm phong

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

Ví dụ: Sử dụng từ khóa sealed cho biến

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)

Lớp trừu tượng đơn giản được xem như một lớp cha cho tất cả các lớp có cùng bản chất. Do đó, mỗi lớp dẫn xuất chỉ có thể kế thừa từ một lớp trừu tượng. Ngoài ra, không thể tạo một biến của lớp trừu tượng. Lớp trừu tượng có thể có các phương thức trừu tượng hoặc không trừu tượng. Lớp trừu tượng không thể được khởi tạo và phải được lớp dẫn xuất thực hiện các phương thức trừu tượng.

Phương thức 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 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ụ: Phương thức trừu tượng

public abstract void draw();

Lớp trừu tượng

Lớp trừu tượng trong C# là một lớp được khai báo là trừu tượng. Nó có thể có các phương pháp trừu tượng và không trừu tượng. Nó không thể được khởi tạo. 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. Lớp trừu tượng buộc các lớp dẫn xuất phải thực hiện tất cả các phương thức trừu tượng.

Ví dụ: Lớp trừu tượng

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 rectangle... Drawing circle...

Giao diện (Interface) trong C

Giao diện (interface) trong C# là một khuôn mẫu mà một đối tượng có thể triển khai (implement) nó. Một giao diện chỉ định các phương thức và thuộc tính mà một lớp triển khai phải có.

Một số điểm cần lưu ý khi làm việc với giao diện:

  • Lớp kế thừa không thể định nghĩa lại các hằng số đã được định nghĩa trong giao diện.
  • Lớp triển khai phải định nghĩa đúng các phương thức đã được định nghĩa trong giao diện.
  • Lớp triển khai phải định nghĩa đúng mức truy cập các phương thức đã được định nghĩa trong giao diện.
  • Một interface chứa các hành vi (action) mà một class triển khai.
  • Một interface có thể bao gồm bất kỳ số 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 kỳ hàm constructor nào.
  • Tất cả các phương thức trong interface đều là abstract.
  • Một interface không thể chứa một trường nào trừ các trường là 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

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 rectangle... Drawing circle...

Ví dụ: Giao diện không thể chứa dữ liệu

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

Ví dụ: Giao diện không thể là private

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

Ví dụ: Giao diện có thể kế thừa từ nhiều giao diện khác

using System;  public interface Drawable {     void draw(); }  public interface Shape {     void resize(); }  public class Rectangle : Drawable, Shape {     public void draw()     {         Console.WriteLine("Drawing rectangle...");     }      public void resize()     {         Console.WriteLine("Resizing rectangle...");     } }  public class TestInterface {     public static void Main()     {         Rectangle r = new Rectangle();         r.draw();         r.resize();     } }

Kết quả:

Drawing rectangle... Resizing rectangle...

Bài viết này đã giúp bạn hiểu về lập trình hướng đối tượng (OOP) trong Selenium C#. Hy vọng nó đã mang đến thông tin hữu ích cho bạn.

1