【问题标题】:Getting inherited variables获取继承变量
【发布时间】:2012-08-11 08:52:32
【问题描述】:

我对 C#.NET 还是比较陌生,所以我确信我缺少一些明显的东西,但这里是:我无法从特定类中获取一些变量。

有问题的类如下所示:

class AridPlanet : Arid
    {
        public const int area = 95;

    }

如你所见,这个类继承自以下类:

abstract class Arid : Astro
    {
        public const int metal = 2;
        public const int gas = 2;
        public const int crystals = 0;
        public const int fertility = 5;

    }

继承自以下类:

abstract class Astro
    {
        public int metal;
        public int gas;
        public int crystals;
        public int fertility;
        public int area;

    }

我尝试获取以下变量:

class Base
    {
        private int metal;
        private int gas;
        private int crystals;
        private int fertility;
        private int area;
        private List<Structure> structures = new List<Structure>();
        private int position;
        private Astro selectedAstro;

        public Base(Astro astro, int position)
        {
            this.selectedAstro = astro;
            this.metal = selectedAstro.metal;
            this.gas = selectedAstro.gas;
            this.crystals = selectedAstro.crystals;
            this.fertility = selectedAstro.fertility;
            this.area = selectedAstro.area;
            this.position = position;

        //Code ommited
    }
    }

astro 参数作为特定的 astro 类型传递给 Base 构造函数,例如 AridMoon

当我运行代码查看 Base 变量分配给什么时,我看到它们都分配给了 0。对我来说,这表明代码正在尝试从 @ 的最顶层超类分配变量987654329@ 即Astro

但是,正如我所理解的继承,编译器应该先查看指定的类,然后再转到超类。

对出了什么问题有任何想法吗?我确定这是我误解的简单事情。

【问题讨论】:

  • 常量不是变量(或字段——这将是正确的术语)。
  • 你可能想看看你的编译器警告...
  • 当然,它们不会改变,所以常量是有意义的,或者readonly 我不完全确定其中的区别。无论哪种情况,我都无法获取和分配值。
  • 编译器说:Warning 1 'AEBaseCalcCSharp.GaiaMoon.area' hides inherited member 'AEBaseCalcCSharp.Astro.area'. Use the new keyword if hiding was intended. 不完全确定这告诉我什么,谁能解释一下?

标签: c# .net inheritance polymorphism


【解决方案1】:

我认为这是你应该做的:

class AridPlanet : Arid
{
    public AridPlanet()
    {
        area = 95;
    }
}

abstract class Arid : Astro
{
    public Arid()
    {
        metal = 2;
        gas = 2;
        crystals = 0;
        fertility = 5;
    }

}

然后将 Astro 类字段访问修饰符更改为 protected 并创建具有 public 访问权限的相应 只读属性

编辑:

abstract class Astro
{
    protected int metal;
    protected int gas;
    protected int crystals;
    protected int fertility;
    protected int area;

    public int Metal { get { return metal; } }
    public int Gas { get { return gas; } }
    public int Crystals { get { return crystals; } }
    public int Fertility { get { return fertility; } }
    public int Area { get { return area; } }
}

class BaseCalc
{
    private int metal;
    private int gas;
    private int crystals;
    private int fertility;
    private int area;
    //private List<Structure> structures = new List<Structure>();
    private int position;
    private Astro selectedAstro;

    public BaseCalc(Astro astro, int position)
    {
        this.selectedAstro = astro;
        this.metal = selectedAstro.Metal;
        this.gas = selectedAstro.Gas;
        this.crystals = selectedAstro.Crystals;
        this.fertility = selectedAstro.Fertility;
        this.area = selectedAstro.Area;
        this.position = position;

        //Code ommited
    }
}

【讨论】:

  • 我不完全确定您所说的“创建具有公共访问权限的相应只读属性”是什么意思,因为 Base 类无法访问受保护的字段。但除此之外,您的回答表明该程序首先在 Astro 中查找,而不是我指出的子类。正如我上面所说,这不是我理解继承工作的方式。
  • 我已经编辑了答案。如果您想了解继承的工作原理,这里有很多示例。这是 msdn 上的继承说明链接:msdn.microsoft.com/en-us/library/ms173149.aspx
【解决方案2】:

让我在这里用一个例子来说明你的工作:

  • 创建一个“汽车”类并定义汽车必须具有的一些属性
  • 创建一个“Sportscar”类,扩展“Car”类并为属性赋值
  • 使用“Car”类的实例,奇怪为什么它不知道 Sportscar。

看起来好像您正在寻找使用多态性。使用接口或抽象类(如 Eric 所示)作为确定每个派生类必须具有的信息和能力的基类。当您创建子类型的新实例时,您可以将其存储为接口的类型,并且对实例的所有调用都将委托给子类。重要的部分是,你调用了哪个构造函数。

【讨论】:

    【解决方案3】:

    如果你引用Astro astro,你实际上会得到Astro 中定义的常量。您必须将其强制转换为特定的子类才能获取该子类中定义的常量。

    您可能正在寻找的是虚拟属性。

    你可以定义

    abstract class Base 
    {
        abstract public int Metal { get; }
    }
    

    然后你可以在子类中实现那个抽象方法

    public class AridPlanet : Base
    {
        const int ARID_PLANET_METAL = 2;
        public override int Metal { get { return ARID_PLANET_METAL; } }
    }
    

    我跳过了您的层次结构的中间级别,但希望它能说明这一点。中间类可以覆盖抽象定义。它们的子类可以选择提供额外的覆盖或接受来自中间类的覆盖。

    【讨论】:

    • @Jagannath 摘要暗示虚拟。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 2014-10-06
    • 2016-06-01
    • 1970-01-01
    • 2018-08-13
    • 2012-11-05
    相关资源
    最近更新 更多