如果对象的引用变量是超类类型,是否可以访问子类的属性?

时间:2019-03-22 17:28:18

标签: c#

我是编程和C#的新手,我只是想知道如果我的引用变量是超类类型,是否可以通过属性初始化子类字段。

示例

Character test = new Archer();
test.Damage = 5; // Damage is from the Fighter Class

SuperClass 字符

abstract class Character
{
//Superclass common
}

字符

战斗机子类
abstract class Fighter : Character
{
    private int damage
    public int Damage {
        get
        {
            return damage;
        }
        set
        {
            damage = value;
        }
    }
}

战斗机

Archer 子类
class Archer : Fighter
{
//stuffs that only archers can do
}

2 个答案:

答案 0 :(得分:9)

  

我是编程和c#的新手

欢迎您的光临。首先,我要鼓励您获得一本好书,上一门课程,找一位导师,或者您为学习一门学科所做的一切。 StackOverflow显然不是教程站点

  

如果我的引用变量是超类类型,是否可以通过属性初始化子类字段?

初学者程序员的答案是:不。

如果要访问派生类型更多的属性,则必须知道该引用属于该派生类型。

C#是我们所谓的“静态类型”语言,这意味着必须有“静态”(即编译器已知)类型信息,以证明每个表达式都是有效的。

高级程序员的答案是:是的,但是不要这样做。

C#具有“动态”模式;如果你说

dynamic test = new Archer();
test.Damage = 123;

那行得通。 不这样做。有两个原因。首先,如果您关闭静态类型检查,则会关闭静态类型检查。你可以写

dynamic test = new Archer();
test.Damaeg = 123;

,编译器将允许它,并且您的程序将在运行时崩溃。 静态类型检查可为您提供帮助。使用它。

第二,我们添加了dynamic,以便人们可以编写与动态语言(例如Python和JavaScript)交互的C#程序。为此,请在需要时使用它,而不是最终绕过静态类型检查。

  

我应该使用最具体的课程吗?

您应该使用一个足够具体的类。在这种情况下,可以使用FighterArcher

我们正在查看您的代码时,还有其他一些评论:

private int damage
public int Damage {
    get
    {
        return damage;
    }
    set
    {
        damage = value;
    }

那是正确的,但是这就是您在C#1.0中编写它的方式。从3.0以后的任何版本的C#中,您通常都会编写简短得多的形式:

public int Damage { get; set; }

,让编译器为您管理后备字段。

还请考虑:*您是否想在类层次结构之外设置Damage属性?如果答案为“否”,则将其设置为protected set;属性。您是否希望在Fighter类之外设置它?如果不是,请将其设置为private set;,是否希望它在初始设置后就可以全部设置为 ?如果否,则(在C#7中)完全省略set,它将只能在构造函数中设置。

此外,这可能对您现在来说太高级了,但它也可能使您走上一条艰难的道路。我写了一系列文章,专门讨论您正在探索的问题空间,以及即使是高级程序员也可能遇到的常见陷阱。它从这里开始:https://ericlippert.com/2015/04/27/wizards-and-warriors-part-one/-在该系列中,我还将详细讨论滥用dynamic

答案 1 :(得分:0)

回答问题,您可以设置值,您只需要在以下位置进行强制转换即可:

(test as Archer).Damage = 5; 
//Or
//(test as Fighter).Damage = 5;

现在,如果您应该这样做,请查看Eric的答案和他的博客。