Tôi có xu hướng chỉ đưa các nhu yếu phẩm (thuộc tính được lưu trữ, bộ khởi tạo) vào các định nghĩa lớp của tôi và chuyển mọi thứ khác thành của riêng chúng extension, giống như một extensionkhối logic mà tôi sẽ nhóm cùng // MARK:.
Ví dụ, đối với một lớp con UIView, tôi sẽ kết thúc bằng một phần mở rộng cho các nội dung liên quan đến bố cục, một phần để đăng ký và xử lý các sự kiện, v.v. Trong các tiện ích mở rộng này, tôi chắc chắn phải ghi đè một số phương thức UIKit, vd layoutSubviews. Tôi không bao giờ nhận thấy bất kỳ vấn đề với phương pháp này - cho đến ngày hôm nay.
Lấy hệ thống phân cấp lớp này làm ví dụ:
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
Đầu ra là A B C. Điều đó làm cho rất ít ý nghĩa với tôi. Tôi đọc về Tiện ích mở rộng Giao thức được gửi tĩnh, nhưng đây không phải là giao thức. Đây là một lớp thông thường và tôi hy vọng các lệnh gọi phương thức sẽ được gửi động khi chạy. Rõ ràng cuộc gọi trên Cít nhất nên được gửi đi năng động và sản xuất C?
Nếu tôi loại bỏ sự kế thừa từ NSObjectvà tạo Cmột lớp gốc, trình biên dịch sẽ phàn nàn rằng declarations in extensions cannot override yettôi đã đọc về nó. Nhưng làm thế nào để có NSObjectmột lớp gốc thay đổi mọi thứ?
Di chuyển cả hai phần ghi đè vào khai báo lớp của chúng tạo ra A A Anhư mong đợi, chỉ di chuyển Bsản phẩm A B B, chỉ di chuyển Asản phẩm C B C, điều cuối cùng hoàn toàn không có ý nghĩa với tôi: thậm chí không phải là người được nhập tĩnh để Atạo ra thông số Anữa!
Việc thêm dynamictừ khóa vào định nghĩa hoặc ghi đè dường như mang lại cho tôi hành vi mong muốn 'từ thời điểm đó trong hệ thống phân cấp lớp trở xuống' ...
Hãy thay đổi ví dụ của chúng tôi thành một cái gì đó ít được xây dựng hơn, những gì thực sự khiến tôi đăng câu hỏi này:
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
Bây giờ chúng tôi nhận được A B A. Ở đây tôi không thể làm cho layout của UIView trở nên linh hoạt bằng mọi cách.
Di chuyển cả hai phần ghi đè vào khai báo lớp của chúng sẽ đưa chúng ta A A Atrở lại, chỉ A hoặc chỉ B vẫn nhận được chúng ta A B A. dynamicmột lần nữa giải quyết vấn đề của tôi.
Về lý thuyết tôi có thể thêm dynamicvào tất cả những overridegì tôi từng làm nhưng tôi cảm thấy như mình đang làm gì đó sai ở đây.
Có thực sự sai khi sử dụng extensions để nhóm mã như tôi không?