继承、隐藏和覆盖
Inheritance, hiding and overriding
一个关于继承、隐藏和覆盖的小问题
我有以下 类:
public class A
{
public BasicProject project { get; set; }
public int a {get; set;}
}
public class B : A
{
public AdvancedProject project { get; set; }
public int b {get; set;}
}
public class C : A
{
public new AdvancedProject project { get; set; }
public int c {get; set;}
}
public class BasicProject
{
public int p1 {get; set;}
public int p2 {get; set;}
}
public class AdvancedProject : BasicProject
{
public int p3 {get; set;}
public int p4 {get; set;}
}
我还有一些功能
A show(A x)
{
x.project.p1;
x.project.p2;
x.project.p3;
x.project.p4;
}
问题是,当我将 B
(或 C
)类型的对象传递给函数时,x.project
指的是类型 BasicProject
而不是 AdvancedProject
.
一种处理方法是:
A show(A x)
{
x.project.p1;
x.project.p2;
var y = x as B;
if(y != null)
y.project.p3;
y.project.p4;
}
var z = x as C;
if(z != null)
z.project.p3;
z.project.p4;
}
}
但是,这是对继承的滥用,我不推荐这样做。
您所描述的行为是设计使然,您不应该试图违背它。
如果将 A
类型的参数传递给方法,该方法只知道它是 A
类型。实际引用可能是从 A
继承的 class 的实例,但该方法并不知道这一点。
你几乎总是想避免强制转换某些东西以查看底层类型是什么。这违背了继承和强类型的目的。我们可以让我们所有的方法参数 object
然后尝试转换它们以查看它们是什么类型。如果您发现自己必须这样做,则表明出现了问题,最好在继续之前回溯并解决问题。
不清楚 Show
是什么,但也许那应该是 BasicProject
的一个方法,AdvancedProject
可以覆盖它。或者这两个 classes 有一个方法可以产生一些输出(比如值的集合)并且 Show
调用该方法并对这些值执行某些操作。
这样 Show
就不必知道它是在与 BasicProject
还是 AdvancedProject
通话。它只是调用了 class 的一个方法,结果根据它正在与之交谈的类型而有所不同。这就是多态。您与您所了解的类型 (BasicProject
) 进行交互,而不知道您实际上是否在处理继承的 class。您只想 "know" 传递给方法的类型。
例如:
public class BasicProject
{
public int p1 { get; set; }
public int p2 { get; set; }
public virtual IEnumerable<int> GetValues()
{
return new [] {p1, p2};
}
}
public class AdvancedProject : BasicProject
{
public int p3 { get; set; }
public int p4 { get; set; }
public override IEnumerable<int> GetValues()
{
var values = new List<int>(base.GetValues());
values.Add(p3);
values.Add(p4);
return values;
}
}
public class AdvancedProject : BasicProject
{
public int p3 {get; set;}
public int p4 {get; set;}
}
现在您的方法 Show
只需调用 GetValues()
函数。如果项目是 BasicProject
,它会得到一组值,如果它是 AdvancedProject
,它会得到另一组值。但它永远不需要知道 属性 是哪种类型。
并且无需继承 A
.
这是 Liskov Substitution Principle 的一部分。它基本上是说,如果你有一个调用类型 A
的参数的方法,那么你可以替换从 A
继承的任何对象的实例。您不必知道或关心实际类型是什么。就您而言,它是 A
,这就是您需要知道的全部内容。
一个关于继承、隐藏和覆盖的小问题
我有以下 类:
public class A
{
public BasicProject project { get; set; }
public int a {get; set;}
}
public class B : A
{
public AdvancedProject project { get; set; }
public int b {get; set;}
}
public class C : A
{
public new AdvancedProject project { get; set; }
public int c {get; set;}
}
public class BasicProject
{
public int p1 {get; set;}
public int p2 {get; set;}
}
public class AdvancedProject : BasicProject
{
public int p3 {get; set;}
public int p4 {get; set;}
}
我还有一些功能
A show(A x)
{
x.project.p1;
x.project.p2;
x.project.p3;
x.project.p4;
}
问题是,当我将 B
(或 C
)类型的对象传递给函数时,x.project
指的是类型 BasicProject
而不是 AdvancedProject
.
一种处理方法是:
A show(A x)
{
x.project.p1;
x.project.p2;
var y = x as B;
if(y != null)
y.project.p3;
y.project.p4;
}
var z = x as C;
if(z != null)
z.project.p3;
z.project.p4;
}
}
但是,这是对继承的滥用,我不推荐这样做。
您所描述的行为是设计使然,您不应该试图违背它。
如果将 A
类型的参数传递给方法,该方法只知道它是 A
类型。实际引用可能是从 A
继承的 class 的实例,但该方法并不知道这一点。
你几乎总是想避免强制转换某些东西以查看底层类型是什么。这违背了继承和强类型的目的。我们可以让我们所有的方法参数 object
然后尝试转换它们以查看它们是什么类型。如果您发现自己必须这样做,则表明出现了问题,最好在继续之前回溯并解决问题。
不清楚 Show
是什么,但也许那应该是 BasicProject
的一个方法,AdvancedProject
可以覆盖它。或者这两个 classes 有一个方法可以产生一些输出(比如值的集合)并且 Show
调用该方法并对这些值执行某些操作。
这样 Show
就不必知道它是在与 BasicProject
还是 AdvancedProject
通话。它只是调用了 class 的一个方法,结果根据它正在与之交谈的类型而有所不同。这就是多态。您与您所了解的类型 (BasicProject
) 进行交互,而不知道您实际上是否在处理继承的 class。您只想 "know" 传递给方法的类型。
例如:
public class BasicProject
{
public int p1 { get; set; }
public int p2 { get; set; }
public virtual IEnumerable<int> GetValues()
{
return new [] {p1, p2};
}
}
public class AdvancedProject : BasicProject
{
public int p3 { get; set; }
public int p4 { get; set; }
public override IEnumerable<int> GetValues()
{
var values = new List<int>(base.GetValues());
values.Add(p3);
values.Add(p4);
return values;
}
}
public class AdvancedProject : BasicProject
{
public int p3 {get; set;}
public int p4 {get; set;}
}
现在您的方法 Show
只需调用 GetValues()
函数。如果项目是 BasicProject
,它会得到一组值,如果它是 AdvancedProject
,它会得到另一组值。但它永远不需要知道 属性 是哪种类型。
并且无需继承 A
.
这是 Liskov Substitution Principle 的一部分。它基本上是说,如果你有一个调用类型 A
的参数的方法,那么你可以替换从 A
继承的任何对象的实例。您不必知道或关心实际类型是什么。就您而言,它是 A
,这就是您需要知道的全部内容。