Trong ngôn ngữ lập trình Swift, một lớp có thể kế thừa các thuộc tính, phương thức và các đặc điểm khác từ một lớp khác. Việc kế thừa các thuộc tính và thuộc tính này từ lớp này sang lớp khác được gọi là kế thừa.
Các bài viết khác:
Khái niệm về kế thừa
Trong lập trình hướng đối tượng, kế thừa là một khái niệm quan trọng cho phép lớp (class) mới được tạo ra dựa trên một lớp hiện có. Lớp mới được gọi là “lớp con” (subclass) và lớp hiện có được gọi là “lớp cha” (superclass) hoặc “lớp cơ sở” (base class).
Khi lớp con kế thừa từ lớp cha, nó sẽ tự động kế thừa tất cả các thuộc tính và phương thức của lớp cha, bao gồm cả các phương thức khởi tạo. Lớp con có thể sử dụng các thuộc tính và phương thức đã có của lớp cha, và cũng có thể định nghĩa thêm các thuộc tính và phương thức riêng của nó.
Kế thừa cho phép chúng ta xây dựng các cấu trúc dữ liệu và hành vi phức tạp bằng cách sử dụng lại mã nguồn đã có, tạo ra sự tái sử dụng mã và giảm thiểu việc lặp lại. Nó cũng giúp tạo ra các mối quan hệ “is-a” (là một) giữa các lớp, cho phép chúng ta áp dụng nguyên tắc đa hình và trừu tượng.
Một số thuật ngữ liên quan đến kế thừa bao gồm:
- Lớp cha (superclass): Lớp đã tồn tại và mà lớp con được kế thừa từ đó. Lớp cha chứa các thuộc tính và phương thức mà lớp con có thể sử dụng hoặc ghi đè.
- Lớp con (subclass): Lớp mới được tạo ra dựa trên lớp cha. Lớp con kế thừa tất cả các thuộc tính và phương thức của lớp cha và có thể định nghĩa thêm các thuộc tính và phương thức riêng của nó.
- Kế thừa đơn (single inheritance): Một lớp con chỉ kế thừa từ một lớp cha duy nhất.
- Kế thừa đa cấp (multilevel inheritance): Một lớp con có thể kế thừa từ một lớp cha và cũng có thể được kế thừa bởi một lớp khác. Điều này tạo ra một chuỗi kế thừa đa cấp.
- Ghi đè (override): Lớp con có thể ghi đè lớp cha
Xem thêm Abstract Classes trong Dart
Kế thừa trong Swift
Trong ngôn ngữ lập trình Swift, kế thừa được thực hiện bằng từ khóa class
. Dưới đây là cách thực hiện kế thừa trong Swift:
- Định nghĩa lớp con: Để tạo một lớp con trong Swift, sử dụng từ khóa
class
theo sau là tên của lớp con, dấu hai chấm:
, và tên của lớp cha mà bạn muốn kế thừa từ đó.
Ví dụ: Tạo một lớp con Square
kế thừa từ lớp cha
class Square: Shape { // Các thuộc tính và phương thức của lớp Square }
- Kế thừa thuộc tính và phương thức: Lớp con sẽ tự động kế thừa tất cả thuộc tính và phương thức có sẵn trong lớp cha. Điều này bao gồm cả thuộc tính tính (computed properties) và thuộc tính lưu trữ (stored properties), cũng như các phương thức.
- Ghi đè phương thức: Trong Swift, lớp con có thể ghi đè (override) các phương thức của lớp cha bằng cách định nghĩa lại chúng. Điều này cho phép lớp con thay đổi hoặc mở rộng hành vi của phương thức đã có trong lớp cha.Để ghi đè một phương thức, sử dụng từ khóa
override
trước định nghĩa của phương thức trong lớp con.
Ví dụ:
class Square: Shape { override func calculateArea() -> Double { // Thực hiện tính diện tích của hình vuông // và trả về kết quả } }
Trong ví dụ trên, lớp con Square
ghi đè phương thức calculateArea
đã có trong lớp cha Shape
và cung cấp một cách tính diện tích mới cho hình vuông.
- Ghi đè thuộc tính: Lớp con cũng có thể ghi đè (override) các thuộc tính tính (computed properties) và thuộc tính lưu trữ (stored properties) của lớp cha bằng cách định nghĩa lại chúng. Điều này cho phép lớp con cung cấp giá trị hoặc cách tính toán mới cho thuộc tính đã có trong lớp cha.Để ghi đè một thuộc tính, sử dụng từ khóa
override
trước định nghĩa của thuộc tính trong lớp con.
Xem thêm kế thừa trong c++
Tính trừu tượng trong kế thừa
Tính trừu tượng (abstraction) là một khái niệm quan trọng trong kế thừa. Nó cho phép chúng ta tạo ra các lớp trừu tượng (abstract class) và các phương thức trừu tượng (abstract method) mà không cần cung cấp một cài đặt cụ thể.
Trong kế thừa, lớp trừu tượng là một lớp mà bạn không muốn tạo ra các thể hiện trực tiếp từ đó. Thay vào đó, lớp trừu tượng chỉ định các đặc điểm chung và giao diện cho các lớp con kế thừa từ nó. Lớp trừu tượng có thể chứa các phương thức trừu tượng, thuộc tính trừu tượng và các phần tử trừu tượng khác.
Phương thức trừu tượng là một phương thức mà chỉ có khai báo mà không có cài đặt cụ thể trong lớp trừu tượng. Nó được định nghĩa bằng cách sử dụng từ khóa abstract
trước khai báo phương thức. Các lớp con kế thừa từ lớp trừu tượng phải cung cấp cài đặt cho các phương thức trừu tượng này.
Việc sử dụng tính trừu tượng trong kế thừa giúp tạo ra một cấu trúc logic và giao diện chung cho các lớp con. Nó giúp tách riêng khái niệm của một lớp và định nghĩa các hành vi chung mà các lớp con có thể tuân thủ.
Dưới đây là ví dụ về lớp trừu tượng và phương thức trừu tượng trong Swift:
// Lớp trừu tượng abstract class Shape { // Phương thức trừu tượng func calculateArea() -> Double { fatalError("Subclasses must override the calculateArea method.") } } // Lớp con kế thừa từ lớp trừu tượng class Square: Shape { let sideLength: Double init(sideLength: Double) { self.sideLength = sideLength } // Ghi đè phương thức trừu tượng override func calculateArea() -> Double { return sideLength * sideLength } } // Tạo một thể hiện của lớp Square let square = Square(sideLength: 5.0) let area = square.calculateArea() // Kết quả: 25.0
Trong ví dụ trên, lớp Shape
là một lớp trừu tượng có một phương thức trừu tượng calculateArea
.
Xem thêm Bài toán rút gọn lũy thừa Module
Kế thừa và giao thức
Kế thừa (inheritance) và giao thức (protocols) là hai khái niệm quan trọng trong lập trình hướng đối tượng và Swift. Dưới đây là cách kết hợp kế thừa và giao thức trong Swift:
- Kế thừa với giao thức: Khi một lớp kế thừa từ một lớp cha, nó cũng có thể tuân thủ các giao thức mà lớp cha đang thực thi. Điều này có nghĩa là lớp con không chỉ kế thừa các thuộc tính và phương thức của lớp cha mà còn phải tuân thủ các yêu cầu của giao thức.
Ví dụ:
protocol Printable { func print() } class MyClass: Printable { func print() { // Thực hiện in } }
Trong ví dụ trên, lớp MyClass
kế thừa giao thức Printable
và cung cấp cài đặt cho phương thức print
được định nghĩa trong giao thức.
- Kế thừa từ nhiều giao thức: Một lớp cũng có thể kế thừa từ nhiều giao thức khác nhau. Điều này cho phép lớp con kế thừa và tuân thủ các yêu cầu của nhiều giao thức khác nhau cùng một lúc.
Ví dụ:
protocol Drawable { func draw() } protocol Printable { func print() } class MyShape: Drawable, Printable { func draw() { // Thực hiện vẽ } func print() { // Thực hiện in } }
Trong ví dụ trên, lớp MyShape
kế thừa từ giao thức Drawable
và Printable
và cung cấp cài đặt cho các phương thức draw
và print
của cả hai giao thức.
- Sử dụng giao thức để định nghĩa giao diện chung: Giao thức cung cấp một cách để định nghĩa giao diện chung cho các lớp không liên quan. Khi một lớp tuân thủ một giao thức, nó đảm bảo rằng nó cung cấp cài đặt cho tất cả các yêu cầu của giao thức đó. Điều này cho phép các lớp khác sử dụng lớp tuân thủ giao thức mà không cần biết chi tiết về lớp đó.