2012-02-20 31 views
5

Tại sao nó rằng sau là hợp pháp C#:Thêm accessor để giao tài sản cho phép, nhưng không phải để sở hữu trừu tượng

public interface ISomeInterface 
{ 
    int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassImplementingInterface : ISomeInterface 
{ 
    public int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

nhưng đây không phải là:

public abstract class SomeAbstractClass 
{ 
    public abstract int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassExtendingAbstractClass : SomeAbstractClass 
{ 
    public override int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

Kết quả thứ hai trong những điều sau đây lỗi biên dịch thời gian:

'InterfaceAbstractTest.SomeClassExtendingAbstractClass.SomeProperty.set': cannot override because 'InterfaceAbstractTest.SomeAbstractClass.SomeProperty' does not have an overridable set accessor InterfaceAbstractTest

Lý do không cho phép sau này trong khi cho phép trước?

+0

Tôi nghĩ rằng chúng từ kay ở đây là "ghi đè". Không có phương pháp nào được đặt để ghi đè. –

+0

Hoặc là từ khóa ghi đè được chỉ định ở cấp thuộc tính chứ không phải cấp độ truy cập? Sau khi tất cả, mỗi accessor là một phương pháp riêng biệt khi nó đi xuống với nó. –

+1

Quyền - từ khóa trừu tượng hoạt động ở cấp thuộc tính, không phải cấp độ truy cập. –

Trả lời

3

Bởi vì một người gọi sử dụng giao diện chỉ quan tâm rằng một người thực hiện của giao diện ít nhất thực hiện định nghĩa của giao diện, như @davisoa tiểu bang, trong khi SomeAbstractClass trong ví dụ của bạn xác định một hợp đồng nào trong đó nêu chính xác các loại, khả năng tiếp cận, và (đối với tài sản) khả năng đọc/khả năng ghi của các thành viên.

Nếu bạn sử dụng phản chiếu để lấy PropertyInfo của SomeProperty (từ cơ sở hoặc lớp con), cần phải giải quyết thông tin đó từ đâu đó. Việc cho phép lớp con thay đổi khả năng đọc/ghi được sẽ là phần lớn vi phạm hợp đồng như là một sự thay đổi trong kiểu trả về hoặc danh sách đối số.

Hãy tưởng tượng ví dụ:

SomeAbstractClass sc = new SomeClassExtendingAbstractClass(); 
PropertyInfo pi = sc.GetType().GetProperty("SomeProperty"); 
Console.Out.WriteLine(pi.CanWrite); // What should be printed here? 
2

Điều này là do việc triển khai Giao diện hứa hẹn sẽ có thuộc tính SomeProperty mà bạn có thể "Nhận".

Việc triển khai lớp trừu tượng đang hứa hẹn rằng các lớp con sẽ cung cấp việc triển khai thuộc tính SomeProperty với phương thức nhận công khai.

Cuối cùng, lớp cơ sở đang xác định thứ gì đó phải được ghi đè, trong khi giao diện xác định hợp đồng .

+0

Theo như tôi đang quan tâm, 'SomeClassExtendingAbstractClass' * không * cung cấp thuộc tính' SomeProperty' với phương thức get công khai. Nó là không quan trọng đối với bất cứ ai làm việc chống lại giao diện trừu tượng mà cũng có một setter. Do đó, câu hỏi của tôi. Hãy tưởng tượng nếu mỗi phương thức get/set là phương thức thay thế. Hãy tưởng tượng không thể cung cấp phương thức 'SetValue' chỉ vì bạn đã mở rộng một lớp trừu tượng có phương thức' GetValue'. –

+2

@KentBoogaart đó là điều - họ không chỉ là getters và setters. Thuộc tính là công dân hạng nhất trong .NET và có siêu dữ liệu hợp đồng về khả năng đọc/ghi của chúng được liên kết với thuộc tính. –

1

Bạn đang cố ghi đè toán tử đã đặt không tồn tại. Xác định một phần của thuộc tính trong lớp trừu tượng, hoặc không cố gắng định nghĩa một phần trong lớp bê tông. Vì bạn đã thiết lập như được bảo vệ trong lớp bê tông, tôi đoán là những gì bạn muốn làm là tạo một toán tử được bảo vệ trong định nghĩa trừu tượng.

0

gì là cần thiết là cả hai ghi đè lên các tài sản hiện có và shadow nó với một mới đọc-viết một. Thật không may, .net không cung cấp bất kỳ phương tiện nào của việc ghi đè và đánh bóng một thành viên trong một lớp đơn lẻ. Điều tốt nhất có thể làm là có thể có lớp cơ sở trừu tượng định nghĩa một thuộc tính chỉ đọc không phải ảo cụ thể mà getter gọi một hàm trừu tượng. Một lớp dẫn xuất sau đó có thể đổ bóng thuộc tính bằng một hàm đọc-ghi không ảo gọi hàm giống nhau trong bộ khởi động của nó và một hàm trừu tượng hoặc ảo mới trong setter của nó.

1

Đây là theo thiết kế. Tôi trích dẫn từ thông số kỹ thuật ngôn ngữ C#:

An overriding property declaration must specify the exact same accessibility modifiers, types and name as the inherited property, if the inherited property has only a single accessor (i.e.,... ready only or write-only), the overriding property must include only that accessor.

Lý do đằng sau đó có thể là do các giao diện linh hoạt hơn loại trừu tượng. Giao diện chỉ quan tâm đến mẫu số chung ít nhất chứ không phải toàn bộ việc thực hiện. Tôi nghĩ rằng có những lý do tốt để lựa chọn một thiết kế khác.

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