2014-06-05 13 views
12

Các lớp Swift có giống như một con trỏ isa có thể được ánh xạ lại không?Swift isa pointer remapping hoặc phương pháp được hỗ trợ khác swizzling

Chúng tôi đã thấy Swift uses a more static method dispatch so với mục tiêu-C, trong đó (trừ khi một lớp dịch vụ từ Foundation/NSObject) ngăn chặn kiểu chuyển động dựa trên việc triển khai phương thức remapping khi chạy.

Tôi tự hỏi cách chúng tôi sẽ triển khai các tính năng động dựa trên đánh chặn phương pháp như mẫu quan sát, thông báo, v.v ...? Hiện tại tất cả những thứ này được cung cấp bởi lớp Objective-C, và có thể dễ dàng tích hợp vào Swift. Nhưng, nếu chúng ta muốn cung cấp các loại tính năng này trong một khuôn khổ (hoặc ứng dụng) của chính chúng ta, thì có cần phải thực hiện chúng trong Objective-C không? Tôi cho rằng có một cách để làm điều đó 'nguyên bản'.

Một loại tranh luận phổ biến khác cho mục tiêu-C là ánh xạ lại con trỏ-isa để tạo ra một lớp con khi đang di chuyển. Đây có phải là loại swizzling được hỗ trợ trong Swift? Nếu không phải là những gì cách được hỗ trợ để chặn các lời gọi phương thức tùy ý?

Chỉnh sửa:Như @jatoben chỉ ra, vì arm64 isa-remapping phải được thực hiện bằng cách gọi object_setClass() chứ không phải bằng cách truy cập trực tiếp giá trị. Điều này vẫn được gọi là 'con trỏ isa swizzling'

+0

Không an toàn khi truy cập isa trực tiếp trong Obj-C, hoặc: http://sealiesoftware.com/blog/archive/2013/09/24/objc_explain_Non-pointer_isa.html – jatoben

Trả lời

10

Dường như cả phương thức trao đổi và kỹ thuật ánh xạ lại con trỏ isa chỉ hoạt động nếu lớp Swift có NSObject là siêu lớp (trực tiếp hoặc tiếp tục lên). Nó hiện không hoạt động, khi lớp Swift không có siêu lớp hoặc một số lớp cơ sở không nền tảng khác.

Các thử nghiệm sau đây cho thấy điều này:

Class: Birdy

class Birdy: NSObject {  
    func sayHello() 
    { 
     println("tweet tweet") 
    }  
} 

Class: HodorBirdy

class HodorBirdy: Birdy { 

    override func sayHello() 
    { 
     super.sayHello() 
     println("hodor hodor") 
    } 
} 

Test:

func testExample() {   
    var birdy : Birdy = Birdy() 
    object_setClass(birdy, HodorBirdy.self) 
    birdy.sayHello(); 
} 

Và kết quả được như mong đợi:

tweet tweet 
hodor hodor 

Trong thử nghiệm này cả hai cơ sở hạng nhất và sub-class được tạo ra trước. Mặc dù chúng cũng có thể được tạo động bằng cách sử dụng thời gian chạy Objective-C miễn là lớp có NSObject như một tổ tiên.

Khi một lớp Swift không lấy được từ nền tảng Objective-C, thì trình biên dịch sẽ ưu tiên công văn dựa trên tĩnh hoặc vtable, do đó không rõ ràng cách thức đánh chặn phương thức hoạt động trong trường hợp này!

Trừ khi ngôn ngữ/trình biên dịch đưa ra một khoản trợ cấp cụ thể cho nó, chúng tôi sẽ đề cập đến tính năng động trong việc ưu tiên hiệu suất. (Interception, đó là nền tảng của các hành vi 'động' có thể được thực hiện tại thời gian biên dịch hoặc thời gian chạy. Trong trường hợp tĩnh hoặc vtable-dispatch mà không có một máy ảo, chỉ áp dụng thời gian biên dịch).

+0

Liên quan: Có bình thường (trong ngữ cảnh của ứng dụng Cocoa/CocoaTouch) cho một lớp Swift không có tổ tiên Cocoa/NSObject không? http://stackoverflow.com/q/24057525/404201 –

2

Tôi không thể trả lời câu hỏi của bạn về tương đương "isa" nhanh chóng, nhưng tôi nghĩ rằng tôi biết một phần câu trả lời cho câu hỏi cơ bản của bạn.

Máy quan sát thuộc tính dường như là phương tiện tích hợp cho Mẫu quan sát. Thay vì khám phá thời gian chạy của "loại" (RTTI, những gì có bạn) nó được dệt một cách rõ ràng.

Từ 'Ngôn ngữ lập trình Swift' trang 345:

nhà quan sát tài sản quan sát và đáp ứng với những thay đổi về giá trị của một bất động sản. Người quan sát tài sản được gọi mỗi lần giá trị của một tài sản là được đặt, ngay cả khi giá trị mới giống với giá trị hiện tại của thuộc tính.

Bạn có thể thêm người quan sát thuộc tính vào bất kỳ thuộc tính được lưu trữ nào mà bạn xác định, ngoài các thuộc tính được lưu trữ lười biếng. Bạn cũng có thể thêm người quan sát thuộc tính vào bất kỳ tài sản được thừa kế nào (dù được lưu trữ hoặc tính toán) bằng cách ghi đè thuộc tính trong một lớp con.

Bạn có tùy chọn để xác định một trong hai hoặc cả hai quan sát trên một tài sản :

  • willSet được gọi là ngay trước khi giá trị được lưu trữ.
  • doSet được gọi ngay sau khi giá trị mới được lưu trữ.

Tôi không chắc chắn điều này sẽ diễn ra như thế nào, nhưng tôi bị cuốn hút.

Dựa vào khám phá kiểu thời gian chạy cũng có vẻ như chạy ngược với chính xác kiểu tĩnh mạnh.

+1

Vì vậy, các nhà quan sát tài sản được giới thiệu ngay. (và hữu ích để biết). Nhưng vẫn còn nhiều điều hữu ích hơn để thực hiện với mẫu chặn. . chúng ta hãy xem liệu chúng ta có thể đưa ra câu trả lời trực tiếp hay không. –

+0

Tôi cũng hy vọng các tín đồ của Haskell có thể giải thích rằng việc đóng cửa bằng văn bản đúng cách là cách để đi. Trong khi tôi hy vọng sẽ phát hiện ra sự hỗ trợ rõ ràng cho đồng thời, như kênh và Goroutines. giá như. –

+0

Một trong những cách sử dụng hợp lệ của phương pháp đánh chặn là khả năng mô đun hóa "yêu cầu cắt ngang" theo mô hình Lập trình hướng Aspect. . Người hâm mộ ObjC đã say mê với khả năng thực hiện điều này trong thời gian chạy, thay vì sử dụng công cụ biên dịch thời gian. Trong thực tế, không có khung chính thức AOP cho ObjC là "nguyên liệu thô" cho việc đánh chặn thời gian chạy là đủ tốt để có được. –

Các vấn đề liên quan