2015-08-21 18 views
9

Vì vậy, tôi đã suy nghĩ về một mô hình tùy chỉnh trong dự án của tôi, nhưng tôi không thể làm cho nó hoạt động. Ý tưởng chính là thay đổi typealias trên mọi lớp con để có quyền truy cập vào giao diện cụ thể của lớp con.Swift: ghi đè typealias bên trong phân lớp

protocol InstanceInterface: class { 

    typealias Interface 

    var interface: Interface { get } 
} 

// Baseclass 
protocol FirstClassInterface: class { /* nothing here for the example */ } 

class FirstClass: InstanceInterface, FirstClassInterface { 

    typealias Interface = FirstClassInterface 

    var interface: Interface { return self } 
} 

// Subclass 
protocol SecondClassInterface: FirstClassInterface { 

    func foo() 
} 

class SecondClass: FirstClass, SecondClassInterface { 

    typealias Interface = SecondClassInterface // <--- This does nothing :(

    func foo() { print("hello world") } // Swift 2.0 here 
} 

// Lets say I want to call foo trough the interface 
let test = SecondClass() 

test.interface.foo() // 'Interface' does not have a member named 'foo' 

Có điều gì đó tôi đang làm sai hoặc tôi hiểu nhầm một số khái niệm Swift ở đây ?! Tôi cần phải phân lớp ở đây để không thực hiện mọi thứ từ các giao thức của siêu lớp lặp đi lặp lại. Là mô hình nhỏ của tôi thậm chí có thể? Tôi đánh giá cao sự giúp đỡ nào. :)

Trả lời

6

Thật không may là không có giải pháp tốt cho vấn đề này.

Ý tưởng chính để ghi đè lên typealias sẽ làm việc trong trường hợp này nhưng hãy cân nhắc những điều sau đây:

protocol TakeAndGet { 
    typealias T 
    func take(value: T) 
    func get() -> T 
} 

class FirstClass: TakeAndGet { 
    typealias T = FirstClass 

    var property = 0 

    func take(value: T) { 
     value.property = 4 
    } 

    func get() -> T { 
     return FirstClass() 
    } 
} 

class SecondClass: FirstClass { 

    typealias T = SecondClass 

    var property2 = "hello" 
} 

Nếu typealias của SecondClass ghi đè một trong những khác phương pháp take sẽ làm việc kể từ khi nó mất một lớp con mà có thể được coi là siêu lớp. Nhưng phương thức get không thể chuyển đổi hoàn toàn FirstClass thành SecondClass. Do đó, không thể ghi đè số typealias.

Bây giờ, nếu chúng tôi muốn ghi đè lên chức năng get với get() -> SecondClass, nó sẽ không hoạt động vì nó không có chữ ký giống với chữ ký trong siêu lớp. Ngoài ra, chúng tôi thừa hưởng phương pháp get dẫn đến việc sử dụng không rõ ràng:

SecondClass().get() // which type gets returned? SecondClass or FirstClass 

Vì vậy, bạn phải thử một cách tiếp cận khác.

+1

Tôi thấy điểm này ngay bây giờ. Nhưng vẫn còn có một số loại lỗi hoặc cảnh báo nếu bạn ghi đè lên các typealias bên trong lớp con !? Tôi có nghĩa là nó không có gì, ngay cả đối với ví dụ của bạn nó vẫn sẽ dính vào FirstClass bên trong SecondClass, hoặc tôi lại sai? Điểm đáng chú ý là gì? – DevAndArtist

+1

@DevAndArtist Vấn đề là một 'typealias' không thể bị ghi đè và nếu bạn khai báo một cái mới có cùng tên như trong' SecondClass' nó sẽ đổ bóng cái kia. Điều này có nghĩa là 'T' nằm trong phạm vi' SecondClass' một kiểu khác nhưng không thay đổi 'T' của' FirstClass'. – Qbyte

5

Điều gì đó có thể phù hợp với mục đích của bạn?

class MyClass<T> { 

} 

class MySubclass1: MyClass<String> { 

} 

class MySubclass2: MyClass<Int> { 

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