2015-06-25 12 views
14

tôi có các mã sau:Swift lớp cha chung init không thể truy cập khi xây dựng lớp con của nó

class ILProperty<T> { 
    var value: T? 
    init(_ value: T) { 
     self.value = value 
    } 
} 

typealias ILStringProperty = ilStringProperty<String> 
class ilStringProperty<String>: ILProperty<String> { 
} 

let x = ILStringProperty("X") 

Dòng cuối cùng là một lỗi biên dịch:

'ILStringProperty' cannot be constructed because it has no accessible initializers

Nếu tôi ghi đè lên các init:

override init(_ value: String) { 
    super.init(value) 
} 

sẽ hoạt động nhưng tôi không thích. Tại sao tôi cần ghi đè lên khi tôi không thêm/sửa đổi nó?

Tôi có làm gì sai không?

Cập nhật: Theo dõi câu hỏi để trả lời từ Nikita Leonov và Icaro

đầu tiên liên quan đến tất cả các thuộc tính phải có giá trị mặc định, tôi nghĩ là tôi hài lòng quy tắc này, nơi một var tùy chọn được mặc định với một giá trị nil, isn phải không? Mặc dù tôi viết var value: T? = nil không giải quyết được.

Sau đó, so với cùng phần documentation "Automatic Initializer Inheritance":

superclass initializers are automatically inherited if certain conditions are met

Một điều kiện là:

If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.

Nơi tôi nghĩ rằng các mã trên không đáp ứng. Điều này thực sự sẽ hiệu quả nếu tôi không sử dụng Generics:

class ILProperty { 
    var value: Any? 
    init(_ value: Any) { 
     self.value = value 
    } 
} 
class ILStringProperty: ILProperty { 
} 
let x = ILStringProperty("X") 

Quy tắc này cũng áp dụng cho các lớp học chung?

Trả lời

0

Từ apple documentation:

Swift provides a default initializer for any structure or base class that provides default values for all of its properties and does not provide at least one initializer itself. The default initializer simply creates a new instance with all of its properties set to their default values.

ilStringProperty lớp học của bạn không phải là một lớp cơ sở vì nó kế thừa từ ILProperty vì vậy nó phải có một khởi tạo, nếu bạn tạo một hoặc ghi đè lên một không quan trọng kể từ khi bạn có ít nhất một initializer trong lớp của bạn như là nhanh chóng sẽ không cung cấp cho một miễn phí.

+1

Hm. Bạn đúng rồi. Với quy tắc này trong tâm trí nó nên kế thừa.Nó hoạt động cho lớp không chung chung, nhưng không thành công trên lớp chung - http://swiftstub.com/239455006/ Trường hợp thực sự thú vị. Tôi cũng tìm thấy câu hỏi tương tự trên diễn đàn Apple dev, nhưng chưa được trả lời - https://forums.developer.apple.com/thread/5389 –

+0

Cảm ơn bạn đã liên kết câu hỏi tương tự – jolen

-1

Here là another quote từ Apple documentation

Unlike subclasses in Objective-C, Swift subclasses do not inherit their superclass initializers by default. Swift’s approach prevents a situation in which a simple initializer from a superclass is inherited by a more specialized subclass and is used to create a new instance of the subclass that is not fully or correctly initialized.

Trong các Swift Programming Language document from apple look section "Initializer Inheritance và Overriding".

Tôi không hiểu nỗi thất vọng của bạn nhưng cách xử lý của Swift với trình khởi tạo là tốt hơn.

+0

Ngoài ra còn có ghi chú sau pha bạn đã dán . – AntiMoron

1

Dòng cuối cùng trong mẫu mã của bạn không còn cung cấp lỗi biên dịch nữa (kể từ Swift 3). Không có đề cập đến điều này trong Swift 3 Language Changes, vì vậy tôi chỉ có thể giả định rằng đây là một lỗi.

0

ganzogo được đề cập, có vẻ như nó hoạt động tốt với Swift (3.0) mới nhất. Ngoài ra, tại sao bạn khai báo một lớp riêng biệt để gán cho typealias? Tôi đã thử điều này trong Playground và có vẻ như ok:

class ILProperty<T> { 
    var value: T? 
    init(_ value: T) { 
     self.value = value 
    } 
} 

typealias ILStringProperty = ILProperty<String> 
let x = ILStringProperty("X") 
Các vấn đề liên quan