Tôi có lớp trừu tượng, AbsClass triển khai giao diện, IClass. IClass có một số thuộc tính chỉ với Trình truy cập. AbsClass thực hiện các thuộc tính của IClass là thuộc tính trừu tượng được xác định trong các lớp bắt nguồn từ AbsClass.Thêm bộ truy cập vào thuộc tính trong lớp có nguồn gốc từ lớp trừu tượng chỉ có trình truy cập có được
Vì vậy, tất cả các lớp học có nguồn gốc từ AbsClass cũng cần phải đáp ứng iCLASS bởi có tính chất tương tự với accessors Nhận. Tuy nhiên, trong một số trường hợp, tôi muốn có thể thêm bộ truy cập đã đặt vào các thuộc tính từ IClass. Tuy nhiên, nếu tôi cố gắng ghi đè các thuộc tính trừu tượng trong AbsClass với một bộ accessor tôi nhận được lỗi này
ConcClassA.Bottom.Set không thể ghi đè bởi vì AbsClass.Bottom không có một bộ accessor overridable
Xem ConcClassA bên dưới.
Nếu tôi có một lớp chỉ triển khai giao diện IClass, nhưng không kế thừa từ AbsClass thì tôi có thể thêm người truy cập đã đặt có vấn đề. Xem ConcClassB bên dưới.
Tôi chỉ có thể triển khai IClass theo từng dẫn xuất của AbsClass thay vì trực tiếp cho AbsClass. Tuy nhiên, tôi biết từ thiết kế của tôi rằng mỗi AbsClass cũng cần phải là một IClass vì vậy tôi muốn chỉ định rằng cao hơn trong hệ thống phân cấp.
public interface IClass
{
double Top
{
get;
}
double Bottom
{
get;
}
}
abstract class AbsClass:IClass
{
public abstract double Top
{
get;
}
public abstract double Bottom
{
get;
}
}
class ConcClassA : AbsClass
{
public override double Top
{
get { return 1; }
}
public override double Bottom
{
get { return 1; }
//adding a Set accessor causes error:
//ConcClassA.Bottom.Set cannot override because AbsClass.Bottom does not have an overridable set accessor
//set { }
}
}
class ConcClassB : IClass
{
public double Top
{
get { return 1; }
//added a set accessor to an interface does not cause problem
set { }
}
public double Bottom
{
get { return 1; }
}
}
Cập nhật
Vì vậy, tôi nghĩ rằng điều này sẽ có ý nghĩa hơn nếu tôi giải thích chính xác những gì tôi đang cố gắng để làm chứ không phải sau đó sử dụng các ví dụ trừu tượng. Tôi làm việc cho một công ty Kiến trúc và đây là những đối tượng kinh doanh liên quan đến một dự án thiết kế kiến trúc.
Tôi có lớp trừu tượng RhNodeBuilding đại diện cho một loại tòa nhà trên một dự án. Có một số chức năng chung, như khả năng có sàn, được xác định trong RhNodeBuilding. RhNodeBuilding cũng được thừa kế từ một lớp trừu tượng khác cho phép nó là một phần của cấu trúc cây dự án lớn hơn.
RhNodeBuilding cụ từ một giao diện IBuilding trong đó xác định một số chỉ đọc tài sản mà tất cả các tòa nhà sẽ có thể cung cấp như TopElevation, BottomElevation, Chiều cao, NumberOfFloors vv .etc ..Lưu ý rằng có các loại tòa nhà khác không xuất phát từ RhNodeBuilding, nhưng vẫn cần triển khai IBuilding.
Ngay bây giờ tôi có hai loại có nguồn gốc từ RhNodeBuilding: MassBuilding và FootPrintBuilding. MassBuilding được xác định bằng hình dạng 3D do người dùng tạo. Hình dạng đó có TopElevation và BottomElevation có thể truy cập được thông qua các thuộc tính tương ứng, nhưng bạn không thể chỉnh sửa âm lượng 3D bằng cách thay đổi các thuộc tính.
FootPrintBuilding mặt khác được xác định bằng đường cong khép kín và phạm vi chiều cao để đẩy đường cong đó qua. Vì vậy, không chỉ lớp học có thể trả lại độ cao hiện tại là gì nhưng các độ cao này cũng có thể được thay đổi để xác định lại phạm vi chiều cao.
Tóm lại. Tất cả các tòa nhà (IBuildings) cần để có thể trả về một TopElevation và BottomElevation, nhưng không phải tất cả các tòa nhà nên cho phép TopElevation hoặc BottomElevation được thiết lập trực tiếp. Tất cả RhNodeBuildings là IBuildings, và các lớp học có nguồn gốc từ RhNodeBuilding có thể hoặc có thể không cần để có thể trực tiếp đặt TopElevation và BottomElevation.
public interface IBuilding
{
double Top
{
get;
}
double Bottom
{
get;
}
}
abstract class RhNodeBuilding:IBuilding
{
public abstract double Top
{
get;
}
public abstract double Bottom
{
get;
}
}
class MassBuilding: AbsClass
{
//mass building only returns Top and Bottom properties so it works fine
public override double Bottom
{
get { return 1; }
}
public override double Top
{
get { return 1; }
}
}
class FootPrintBuilding: AbsClass
{
//Top and Bottom of FootPrintBuilding can both be retrieved and set
public override double Top
{
get { return 1; }
//adding a Set accessor causes error:
//cannot override because RhNodeBuilding.Top does not have an overridable set accessor
//set { }
}
public override double Bottom
{
get { return 1; }
//adding a Set accessor causes error:
//cannot override because RhNodeBuilding.Bottom does not have an overridable set accessor
//set { }
}
}
Ngay bây giờ nó có vẻ như lựa chọn tốt nhất là không có RhNodeBuilding thực hiện IBuilding, nhưng thay vì có mỗi lớp dẫn xuất từ RhNodeBuilding thực hiện IBuilding. Bằng cách đó tôi có thể xác định các thuộc tính từ IBuilding trực tiếp thay vì sau đó là ghi đè.
abstract class AltRhNodeBuilding
{
public abstract double Top
{
get;
}
}
class AltFootPrintBuilding: IClass
{
public override double Top
{
get { return 1; }
//Can't add set access to overridden abstract property
set { }
}
//No problem adding set accessor to interface property
public double Bottom
{
get { return 1; }
set { }
}
}
Bạn không phá vỡ giao diện "hợp đồng" bằng cách nói "tài sản này đôi khi chỉ đọc nhưng đôi khi không"? Có lẽ bạn cần phải phá vỡ giao diện của bạn (ví dụ như một giao diện khác) để cho phép những lớp đó chỉ cần đọc và những lớp khác cần đọc/ghi. –
Thiếu trình truy cập thuộc tính không ngụ ý rằng thuộc tính chỉ đọc cho mọi người (nghĩa là nó không thay đổi và giá trị của nó không bao giờ thay đổi) - nó chỉ ngụ ý rằng thuộc tính là chỉ đọc cho khách hàng sử dụng giao diện cụ thể này. Vì vậy, không, nó không phải là một thay đổi hợp đồng phá vỡ. Nó chỉ là giới hạn C#/CLR. –
Đồng ý, giao diện hợp đồng chỉ xác định những gì bạn phải thực hiện, không phải những gì bạn không làm. –