seh*_*rom 3 .net c# polymorphism properties
我有几个类,我遇到从其他类方法访问子类中定义的属性时遇到问题.
我有一个被调用的基类Section和一些子类,例如SectionPlane : Section.在每个子类中,定义了一组不同的字段和属性(在SectionPlane私有字段_t和公共属性t中可以找到,而在SectionExtruded : Section我有私有字段_A和公共属性'A').
课程部分
// General section object
public abstract class Section
{
public Section()
{}
}
Run Code Online (Sandbox Code Playgroud)
类平面部分
// Section object representing a plane with thickness t
public class SectionPlane : Section
{
private double _t;
public SectionPlane(double t)
{
this.t = t;
}
public double t
{
get
{
return _t;
}
set
{
_t = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
类挤压部分
// Section object of some geometry with cross section area A extruded along the element it is assigned to.
public class SectionExtruded : Section
{
private double _A;
public SectionExtruded(double A)
{
this.A = A;
}
public double A
{
get
{
return _A;
}
set
{
_A = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我从类的任何子类Element尝试访问属性时,会出现问题,因为没有在基类中设置Section,例如在元素中Solid2D : Element:
类元素
public abstract class Element
{
private Section _section;
public Element(Section section)
{
this.section = section;
}
public Section section
{
get
{
return _section;
}
set
{
_section = value;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
类Solid 2D元素
// Solid2D elements can only have sections of type SectionPlane
public class Solid2D : Element
{
public Solid2D(SectionPlane section)
: base(section)
{
}
public void Calc()
{
double t = section.t; // This results in error 'Section' does not contain a definition for 't' and no extension method 't' accepting a first argument of type 'Section' could be found (are you missing a using directive or an assembly reference?)
}
}
Run Code Online (Sandbox Code Playgroud)
酒吧元素
// Bar elements can only have sections of type SectionExtruded
public class Solid2D : Element
{
public Solid2D(SectionExtruded section)
: base(section)
{
}
public void Calc()
{
double A = section.A; // This results in error 'Section' does not contain a definition for 'A' and no extension method 'A' accepting a first argument of type 'Section' could be found (are you missing a using directive or an assembly reference?)
}
}
Run Code Online (Sandbox Code Playgroud)
有没有办法访问我的属性t而不必将其包含在基类中Section?这将非常有用,因为并非我将使用的所有部分都具有相同的属性.
因为你知道它只能是SectionPlane你可以投射它
double t = ((SectionPlane)section).t;
Run Code Online (Sandbox Code Playgroud)
如果您不确定是否有正确类型的部分,则可以使用as关键字
double t = 0;
var sectionPane = section as SectionPlane;
if (sectionPane != null) {
t = sectionPane.t;
}
Run Code Online (Sandbox Code Playgroud)
as如果该部分具有其他类型,则不会抛出异常,而是返回null.
或者你可以简单测试一下
double t = 0;
if(section is SectionPlane) {
t = ((SectionPlane)section).t;
}
Run Code Online (Sandbox Code Playgroud)
但这不如使用优雅as,因为你必须测试类型然后再投射它; 但是内部再次进行测试.
使用C#7.0中引入的新模式匹配,您可以编写:
double t = 0;
if(section is SectionPlane sp) {
t = sp.t;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果你必须进行这样的测试,那么问题是,你的方法在面向对象的意义上是否正确.如果将Calc-method 移动到抽象类Section并让每个类执行自己的计算,则不需要进行类型测试或转换.
在Section:
public abstract void Calc();
Run Code Online (Sandbox Code Playgroud)
在 SectionPlane
public override void Calc()
{
var x = t;
}
...
section.Calc(); // No casting or type test required.
Run Code Online (Sandbox Code Playgroud)