Kế thừa lớp là một tính năng cơ bản của OOP (Lập trình hướng đối tượng) giúp bạn tạo phiên bản cụ thể và chuyên biệt hơn của bất kỳ lớp nào.
Đây là một ví dụ :
Food -> Fruit -> Orange
Có một mối quan hệ giữa các lớp này!
Chúng ta có thể nói rằng quả cam là một loại trái cây, nhưng trái cây cũng là thức ăn.
Lớp cha (còn được gọi là siêu lớp hoặc lớp cơ sở ) luôn chung chung hơn các lớp con.
Fruit
(chung chung hơn) là lớp cha của Orange
(cụ thể hơn).
Trong Ruby, nó trông giống như thế này :
class Food end class Fruit < Food end class Orange < Fruit end
Một trong những hàm ý của kế thừa trong Ruby là mọi phương thức &mọi hằng số được xác định trên Food
sẽ có trên Fruit
và cả trên Orange
.
Các phương thức được truyền từ lớp cơ sở, nhưng không phải ngược lại.
Mục đích của Thừa kế là gì?
Bạn có thể nghĩ rằng việc tạo một cấu trúc phân cấp đối tượng cung cấp một số kiểu tổ chức “cảm thấy tốt” cho mã của bạn, nhưng còn nhiều thứ hơn thế nữa.
Kế thừa được sử dụng để tạo một phiên bản khác của lớp cha phù hợp cho một mục đích cụ thể. Có thể nó cần một số tính năng hoặc phương thức bổ sung không có ý nghĩa trong lớp cha.
Đây là một ví dụ :
Tất cả các loại trái cây đều có màu sắc, trọng lượng và tên gọi.
Một số loại trái cây có thể có các đặc điểm đặc biệt không giống với các loại trái cây khác, vì vậy bạn tạo một loại mới kế thừa các đặc điểm của TẤT CẢ các loại trái cây (màu sắc, trọng lượng, v.v.) và sau đó bạn thêm đặc tính đặc biệt.
Đó là ý tôi muốn nói đến sự chuyên môn hóa.
Một ví dụ khác :
Bạn có một lớp ghi vào cơ sở dữ liệu, nhưng bạn muốn một phiên bản khác của lớp (có thể cho mục đích gỡ lỗi) ghi lại tất cả các hoạt động của cơ sở dữ liệu.
Trong trường hợp này, bạn muốn có mẫu trang trí.
Bạn có thể đọc giải thích chi tiết về bài viết này, nhưng ý tưởng cơ bản là bạn sử dụng kế thừa để bao bọc một lớp khác và sau đó thêm một cái gì đó mới vào nó.
Mà không cần phải thay đổi bản gốc!
Thừa kế trong Thế giới Thực
Được rồi.
Chúng tôi đã tìm hiểu về kế thừa, nhưng bạn có biết rằng bạn đang sử dụng nó hàng ngày với tư cách là một nhà phát triển Ruby không?
Bản thân Ruby sử dụng kế thừa để bật các phương pháp như:
-
puts
-
class
-
super
Điều này là do tất cả các đối tượng Ruby đều kế thừa từ Object
theo mặc định.
Vì vậy, nếu bạn tạo một lớp học như thế này :
class Apple end
Lớp cha của nó là Object
:
Apple.superclass # Object
Đó là lý do tại sao bạn có thể sử dụng các phương pháp như những phương pháp được đề cập ở trên.
Ví dụ:khi bạn gọi puts
Ruby tìm kiếm phương thức này trong lớp của bạn.
Sau đó :
- Nó tìm kiếm phương thức trong một trong các lớp cha
- Nếu không tìm thấy, nó sẽ bắt đầu lại từ đối tượng và nó sẽ cố gắng tìm
method_missing
- Nếu không được tìm thấy, nó sẽ tạo ra
NoMethodError
hoặcNameError
nếu phương thức được gọi mà không có đối tượng rõ ràng (a.size
so vớisize
, trong đóa
là đối tượng rõ ràng)
Bạn có thể tìm thêm các ví dụ về kế thừa trong Rails.
Ngay tại đây :
class ApplicationController < ActionController::Base end
Bộ điều khiển :
class SessionsController < ApplicationController end
Mô hình :
class Comment < ApplicationRecord belongs_to :article end
Tính kế thừa có ở khắp mọi nơi trong Ruby, nhưng đôi khi nó không phải là giải pháp phù hợp.
Thành phần:Một sự thay thế cho sự kế thừa
Kế thừa có những hạn chế nhất định.
Ví dụ :
Bạn muốn xây dựng một máy tính từ các bộ phận.
Chúng tôi nói rằng máy tính có các bộ phận, nhưng các bộ phận riêng lẻ tự nó không phải là máy tính.
Nếu bạn tách chúng ra, chúng sẽ không thể thực hiện được chức năng của chúng.
Chúng tôi cần thứ khác…
Chúng tôi cần bố cục!
Thành phần xây dựng các lớp trong đó các phần khác nhau kết hợp với nhau để thực hiện một chức năng.
Cũng giống như một máy tính.
Dưới đây là một ví dụ về bố cục trong thực tế :
class Computer def initialize(memory, disk, cpu) @memory = memory @disk = disk @cpu = cpu end end
Máy tính được cung cấp các bộ phận cần thiết để hoạt động.
Đây là thành phần.
Nguyên tắc thay thế Liskov
Tính kế thừa sẽ mạnh mẽ khi được sử dụng trong những tình huống phù hợp.
Nhưng giống như tất cả các công cụ, nó có thể bị lạm dụng!
Trên thực tế, có một câu trích dẫn phổ biến từ cuốn sách Mẫu thiết kế ban đầu giống như sau:
“Ưu tiên bố cục hơn là kế thừa.”
Mẫu thiết kế:Các yếu tố của phần mềm hướng đối tượng có thể tái sử dụng
Để đảm bảo rằng bạn đang sử dụng kế thừa đúng cách có một nguyên tắc bạn có thể tuân theo, L
từ SOLID.
Nó là viết tắt của "Nguyên tắc thay thế Liskov".
Điều này nói rằng các lớp con của bạn phải có thể được sử dụng thay cho lớp cơ sở của bạn.
Nói cách khác :
Nếu bạn kế thừa từ Fruit
&color
là một chuỗi, bạn không muốn thay đổi color
để trả về một biểu tượng trong một lớp con.
Ví dụ :
Người dùng Fruit
phụ thuộc vào color
trả về một chuỗi.
class Fruit def color "orange" end end
Điều này phá vỡ LSP :
class Orange < Fruit def color :orange end end
Nếu bạn thay đổi color
để trả về một biểu tượng, thì bạn không thể thay thế một Fruit
đối tượng có Orange
.
Tại sao?
Bởi vì nếu bạn gọi một phương thức như split
trên một biểu tượng, bạn sẽ gặp lỗi.
Đó là một phương pháp mà các ký hiệu không có.
Nhưng chuỗi thì có.
Một dấu hiệu đỏ khác là khi lớp con của bạn không phải là một chuyên môn thực sự của lớp cha và bạn chỉ đang sử dụng lớp cha để chia sẻ các phương thức tiện ích.
Tóm tắt
Bạn đã học về kế thừa và cấu tạo trong Ruby!
Bạn có thể sử dụng kế thừa để tạo phiên bản chuyên biệt của lớp mẹ và thành phần để tập hợp các thành phần lại với nhau thành một tổng thể. Hãy nhớ làm theo LSP
nguyên tắc nếu bạn không muốn làm rối tung lên.
Bây giờ bạn có thể viết Mã hướng đối tượng tốt hơn 🙂
Cảm ơn vì đã đọc.