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 extension
khố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ừ NSObject
và tạo C
một lớp gốc, trình biên dịch sẽ phàn nàn rằng declarations in extensions cannot override yet
tôi đã đọc về nó. Nhưng làm thế nào để có NSObject
mộ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 A
như mong đợi, chỉ di chuyển B
sản phẩm A B B
, chỉ di chuyển A
sả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 để A
tạo ra thông số A
nữa!
Việc thêm dynamic
từ 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 A
trở lại, chỉ A hoặc chỉ B vẫn nhận được chúng ta A B A
. dynamic
mộ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 dynamic
vào tất cả những override
gì 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 extension
s để nhóm mã như tôi không?