我们可以在C#中创建基类的子类,比如在SQL中创建表的视图吗?
所需行为的示例:
public class EmployeeSpecificUsage : Employee
{
public string firstName;
public string field1;
public int age;
public string Name; //Error! Not implemented in main class
}
public abstract class Employee
{
public string firstName;
public string lastname;
public int age;
public string workTitle;
public string field1;
public string field2;
public string field3;
}
目的:
答案 0 :(得分:2)
您对子类化的理解不正确。子类化是扩展基类的一种方式,而不是从中取走。无论基类是什么,所有子类都会拥有它。
这与SQL中的视图不同,后者既可以删除列,也可以添加计算列。
虽然继承不允许您减少可见成员的数量,但您可以使用 composition 来执行此操作。在Employee
中换行RestrictedEmployee
,并仅公开您希望其他人看到的成员:
public class EmployeeSpecificUsage {
private readonly Employee wrapped;
public EmployeeSpecificUsage(Employee e) {
wrapped = e;
}
public string firstName => wrapped.firstName;
public string field1 => wrapped.field1;
// Two fields above use C# 6 syntax. If it is not available,
// use syntax below:
public int age {
get {
return wrapped.age;
}
}
}
就禁止添加新字段而言,你不能用继承或组合来做到这一点:如果你允许继承子类(即基类不是sealed
)你就能够添加新成员。组合比继承弱得多,因此您可以通过包装它们来向sealed
类添加新字段。
答案 1 :(得分:1)
接口可以用作视图。
public interface IView
{
string FirstName { get; }
int Age { get; }
string Name { get; }
}
public class Employee: IView
{
// make fields private if possible
private string firstName;
private string lastname;
private int age;
private string workTitle;
private string field1;
private string field2;
private string field3;
// implements IView.FirstName as an auto property
public string FirstName { get; set; }
// implements IView.Age: returns the private age field
public int Age { get { return age;} }
// explicit implementation of IView.Name: visible only as IView
string IView.Name { get { return lastName + ", " + firstName; } }
}
然后:
Employee employee1 = new Employee(); // FirstName and Age are visible on employee1
IView employee2 = new Employee(); // Name is visible, too
答案 2 :(得分:1)
接口允许您访问类的一个方面(而不是实际扩展基类的派生类)。
看看这个:
public class Employee : IEmployeeSpecificUsage
{
public string firstName { get; }
public string lastname { get; }
public int age { get; }
public string workTitle { get; }
public string field1 { get; }
public string field2 { get; }
public string field3 { get; }
}
public interface IEmployeeSpecificUsage
{
public string firstName { get; }
public string field1 { get; }
public int age { get; }
}
如果您通过Employee
界面引用IEmployeeSpecificUsage
实例,则只会"参见"界面中的内容。
但是,如果不更改"基类"则无法添加新接口,因为它必须声明它实现了这些接口。
答案 3 :(得分:0)
如果您想要提供对班级内部字段的只读访问权限,请查看公共带有getter的属性。让您的现场成员受到保护。通过这种方式,您将能够为名称属性实现自定义逻辑,该属性由firstname和lastname字段组成。
public class EmployeeSpecificUsage : Employee
{
public string FirstName { get { return firstName; }};
public string FullName { get { return string.Format("{0} {1}", firstName, lastName); }};
}
public class Employee
{
protected string firstName;
protected string lastname;
protected int age;
protected string workTitle;
protected string field1;
protected string field2;
protected string field3;
}
一个选项是使用受保护的setter和public getter在基类中创建属性。