2009-08-04 8 views
5

Trong một lớp cơ sở tôi có khách sạn này:Tại sao tôi không thể thêm bộ truy cập đã đặt vào thuộc tính được ghi đè?

public virtual string Text 
{ 
    get { return text; } 
} 

Tôi muốn ghi đè lên đó và trả về một văn bản khác nhau, nhưng tôi cũng muốn để có thể thiết lập các văn bản, vì vậy tôi đã làm điều này:

public override string Text 
{ 
    get { return differentText; } 
    set { differentText = value; } 
} 

Tuy nhiên, điều này không hoạt động. Tôi nhận được một màu đỏ squiggly theo set nói rằng tôi không thể ghi đè bởi vì nó không có một bộ accessor. Tại sao điều này là một vấn đề? Tôi nên làm gì?

+0

Tôi muốn làm giống hệt nhau. Nên có thể. –

+0

Có thể nhưng yêu cầu "tầng lớp trung lưu". Ngoài ra nó có lẽ không phải là một ý tưởng tốt trong nhiều tình huống, nhưng có một số ngoại lệ, ví dụ khi ghi đè các thuộc tính trừu tượng. Cơ sở: 'chuỗi trừu tượng công khai Văn bản {get; } '. Trung (thừa kế cơ sở): 'văn bản chuỗi nội bộ được bảo vệ;' 'chuỗi ghi đè niêm phong công khai Văn bản {get {return text; }} '. Trẻ em (kế thừa giữa): 'chuỗi văn bản mới công khai {get {return text; } đặt {text = value; }} '. Bộ sửa đổi nội bộ được bảo vệ và phần ghi đè được đóng kín đảm bảo đóng gói không bị vỡ bên ngoài bộ phận lắp ráp của bạn. – AnorZaken

+0

@AnorZaken: Đó không phải là trọng, đó là bóng tối. Nó không đòi hỏi một lớp "trung bình". – Guffa

Trả lời

3

Trong khối thứ hai của bạn mã bạn đang tạo ra một phương thức thiết lập công, nhưng từ "ghi đè" trong khai báo làm cho trình biên dịch tìm kiếm một phương thức có cùng chữ ký trong lớp cơ sở. Vì nó không thể tìm thấy phương pháp đó, nó sẽ không cho phép bạn tạo tập hợp của bạn.

As ArsenMkrt cho biết bạn có thể thay đổi khai báo cơ sở của mình để chứa tập hợp được bảo vệ. Điều này sẽ cho phép bạn ghi đè nó, nhưng vì bạn vẫn không thể thay đổi chữ ký, bạn không thể quảng cáo phương thức này cho công khai trong lớp con của bạn, vì vậy mã bạn đã đăng vẫn không hoạt động. Thay vào đó, bạn cần phải thêm một phương thức thiết lập ảo công khai vào lớp cơ sở của bạn mà không làm bất cứ điều gì (hoặc thậm chí ném ngoại lệ nếu bạn thử gọi nó) nhưng điều này đi ngược lại những gì người dùng của lớp mong đợi hành vi để được như vậy nếu bạn làm điều này (và tôi sẽ không khuyên bạn nên nó) chắc chắn rằng nó là như vậy cũng ghi nhận rằng người dùng không thể bỏ lỡ nó:

///<summary> 
///Get the Text value of the object 
///NOTE: Setting the value is not supported by this class but may be supported by child classes 
///</summary> 
public virtual string Text 
{ 
    get { return text; } 
    set { } 
} 

//using the class 

BaseClass.Text = "Wibble"; 
if (BaseClass.Text == "Wibble") 
{ 
    //Won't get here (unless the default value is "Wibble") 
} 

nếu không tuyên bố thiết lập như một phương pháp riêng biệt trong lớp con của bạn:

public override string Text 
{ 
    get { return differentText; } 
} 

public void SetText(string value) 
{ 
    differentText = value; 
} 
+0

Tôi không thích nó, nhưng tôi đoán tôi sẽ phải làm một cái gì đó dọc theo dòng có một phương pháp SetText riêng biệt hoặc một cái gì đó ... cảm ơn :) – Svish

+0

Vâng, nó cũng có thể là một vấn đề kiến ​​trúc. Tại sao người dùng không thể đặt giá trị văn bản trong lớp cơ sở? Có * thực sự * cùng một tài sản trong cả hai lớp học? Nó có vẻ là một yêu cầu thông thường để cần một mô hình như thế này. –

+0

Vâng, đó là một số lớp tham số khác nhau chứa các loại giá trị khác nhau. Và tôi muốn tất cả họ có thể tự đại diện cho mình như một giá trị văn bản mà người dùng có thể đọc (để in ví dụ). Nhưng tôi không muốn tất cả các tham số được thiết lập bằng văn bản (phân tích cú pháp gây phiền phức nhiều hơn là in). Ví dụ một tham số ngày tôi muốn in ngày, nhưng tôi không cần phải thiết lập ngày thông qua văn bản, kể từ khi cài đặt sẽ được thực hiện với một datepicker. – Svish

3
public virtual string Text 
{ 
    get { return text; } 
    protected set {} 
} 

thay đổi cơ sở bất động sản như thế này lớp, bạn đang cố gắng để ghi đè phương thức thiết lập mà không tồn tại

+0

Bạn không thể ghi đè lên một setter được bảo vệ như một setter công khai trong lớp con. – Guffa

+0

hmm, đồng ý .... :) –

2

Đó là vấn đề bởi vì bạn đang phá vỡ g đóng gói. Bạn không thể ghi đè lên một cái gì đó và làm cho nó dễ tiếp cận hơn, điều đó sẽ ném mọi thứ về việc đóng gói ra ngoài cửa sổ.

Đó là quy tắc và nó cũng áp dụng trong trường hợp của bạn, dù bạn thực sự đang phơi bày thứ gì đó không phải là giá trị ban đầu.

Không có cách nào để thực hiện chính xác những gì bạn đã thử. Bạn phải thực hiện một setter trong lớp cơ sở, hoặc sử dụng một phương pháp khác để thiết lập giá trị mới.

+0

Lớp con không thể phá vỡ đóng gói bởi vì những gì ông đang làm không thể được thực hiện trừ khi đóng gói đã bị hỏng trong lớp cơ sở đã (nếu trẻ em không được phép truy cập vào trường sao lưu của thuộc tính). Ngoài ra lớp cơ sở đã khai báo thuộc tính là ảo nghĩa là nó được cho là có khả năng thay đổi hành vi của nó - và khi một thuộc tính/phương thức là bất kỳ thứ gì ảo đi! (Miễn là bạn tuân theo tài liệu của nó tất nhiên.) Có hay không _should be_ ảo, hoặc nếu đó phá vỡ đóng gói của lớp cơ sở, là câu hỏi thực sự, và điều đó phụ thuộc. – AnorZaken

+0

@AnorZaken: Bạn đang nói về điều gì? Chỉ vì một thành viên là ảo không có nghĩa là bạn có thể ghi đè lên nó theo bất kỳ cách nào bạn muốn. – Guffa

2

Bạn có thể ẩn các tài sản từ các lớp cơ sở:

public new string Text 
{ 
    get { return differentText; } 
    set { differentText = value; } 
} 

Nhưng trong trường hợp đó rằng bất động sản sẽ chỉ được sử dụng khi thao tác các đối tượng thông qua một biến kiểu này, không phải là kiểu cơ sở

2

Bạn muốn có nhiều khả năng hơn để được hiển thị khi sử dụng một kiểu con. Có vẻ như bạn không muốn ghi đè, bạn muốn bóng. Chỉ cần sử dụng từ khóa mới để ẩn thuộc tính Văn bản chỉ đọc trong thuộc tính có thể đọc/ghi được của bạn.

Trong lớp cơ sở:

protected string text; 
public string Text 
{ 
    get { return text; } 
} 

Trong lớp có nguồn gốc:

new public string Text 
{ 
    get { return text; } 
    set { text = value; } 
} 
+0

Bạn có thể đổ bóng và ghi đè cùng một lúc không? – Svish

+0

Không, chúng có nghĩa là những thứ khác nhau. Cho dù bạn đổ bóng hoặc ghi đè xác định liệu hành vi của Văn bản có bị ảnh hưởng ngay cả sau khi truyền tới loại cơ sở hay không. Xem câu hỏi này để có giải thích tốt hơn: http://stackoverflow.com/questions/673779/what-is-shadowing –