如何覆盖而不是隐藏 C# 子类中的成员变量(字段)?

发布于 2024-12-26 18:38:12 字数 821 浏览 2 评论 0原文

我希望它能告诉我 ItemA 和 ItemB 的名称。它应该告诉我“Subitem\nSubitem”,但它却告诉我“Item\nSubitem”。这是因为 Subitem 类中定义的“Name”变量在技术上与基 Item 类中定义的“Name”变量是不同的变量。我想将原始变量更改为新值。我不明白为什么这不是最简单的事情,考虑到虚拟和覆盖与方法完美配合。我完全无法找出如何实际覆盖变量。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine(ItemA.Name);
            System.Console.WriteLine(ItemB.Name);
            System.Console.ReadKey();
        }
        static Item ItemA = new Subitem();
        static Subitem ItemB = new Subitem();
    }
    public class Item
    {
        public string Name = "Item";
    }
    public class Subitem : Item
    {
        new public string Name = "Subitem";
    }
}

I want this to tell me the Name of both ItemA and ItemB. It should tell me "Subitem\nSubitem", but instead it tells me "Item\nSubitem". This is because the "Name" variable defined in the Subitem class is technically a different variable than the "Name" variable defined in the base Item class. I want to change the original variable to a new value. I don't understand why this isn't the easiest thing ever, considering virtual and override work perfectly with methods. I've been completely unable to find out how to actually override a variable.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example
{
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine(ItemA.Name);
            System.Console.WriteLine(ItemB.Name);
            System.Console.ReadKey();
        }
        static Item ItemA = new Subitem();
        static Subitem ItemB = new Subitem();
    }
    public class Item
    {
        public string Name = "Item";
    }
    public class Subitem : Item
    {
        new public string Name = "Subitem";
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

遗心遗梦遗幸福 2025-01-02 18:38:12

您无法覆盖 C# 中的变量,但可以覆盖属性:

public class Item
{
    public virtual string Name {get; protected set;}
}
public class Subitem : Item
{
    public override string Name {get; protected set;}
}

另一种方法是更改​​子类中的值,如下所示:

public class Item
{
    public string Name = "Item";
}
public class Subitem : Item
{
    public Subitem()
    {
        Name = "Subitem";
    }
}

You cannot override variables in C#, but you can override properties:

public class Item
{
    public virtual string Name {get; protected set;}
}
public class Subitem : Item
{
    public override string Name {get; protected set;}
}

Another approach would be to change the value in the subclass, like this:

public class Item
{
    public string Name = "Item";
}
public class Subitem : Item
{
    public Subitem()
    {
        Name = "Subitem";
    }
}
空城之時有危險 2025-01-02 18:38:12

对于字段(即所谓的变量),不存在多态性的概念(这就是使 override 执行其操作的原因)。这里你需要使用的是一个属性。

public class Item
{
    public virtual string Name
    {
        get { return "Item"; }
    }
}

public class SubItem : Item
{
    public override string Name
    {
        get { return "Subitem"; }
    }
}

There is no concept of polymorphism (which is what makes override do its thing) with fields (what you call a variables). What you need to use here instead is a property.

public class Item
{
    public virtual string Name
    {
        get { return "Item"; }
    }
}

public class SubItem : Item
{
    public override string Name
    {
        get { return "Subitem"; }
    }
}
不离久伴 2025-01-02 18:38:12

“覆盖变量”是什么意思?

变量是概念内存中的命名位置(“概念”,因为它可能是寄存器,但不太可能是字段)。

重写方法将一组操作替换为另一组操作。

既然内存中的命名位置不是一组操作,那么如何替换它呢?期望使用内存中指定位置的事情应该做什么?

如果要更改内存中存储的内容,只需在构造派生类时执行此操作:

public class Item
{
  public string Name = "Item";
}
public class Subitem : Item
{
  public SubItem()
  {
    Name = "Subitem";
  }
}

如果要重写一组操作,则定义要重写的一组操作(方法或属性)。

What would "overriding a variable" mean?

A variable is a named location in conceptual memory ("conceptual", because it could be a register, though not very likely with fields).

Overriding a method substitutes one set of operations for another.

Since a named location in memory isn't a set of operations, how can you substitute it? What are things that expect to use that named location in memory supposed to do?

If you want to change what is stored in the memory, then just do so when the derived class is constructed:

public class Item
{
  public string Name = "Item";
}
public class Subitem : Item
{
  public SubItem()
  {
    Name = "Subitem";
  }
}

If you want to override as set of operations, then define a set of operations (a method or property) to override.

鲸落 2025-01-02 18:38:12

这个问题相对较旧,作者可能使用的是 C# 5.0 或更低版本。但我有同样的问题,并遇到了一个非常巧妙的解决方案,适用于 C# 6.0 及更高版本,我想与您分享:

C# 6.0 提供了初始化自动属性的能力。所以人们可以使用这样的方法:

public class Item
{
    public virtual string Name { get; set; } = "Item";
}

public class Subitem : Item
{
    public override string Name { get; set; } = "Subitem";
}

This question is relatively old and the author was probably using C# 5.0 or lower. But I had the same question and came across a very neat solution that works with C# 6.0 and higher that I want to share with you:

C# 6.0 gives the ability to initialize auto-properties. So one can use just that:

public class Item
{
    public virtual string Name { get; set; } = "Item";
}

public class Subitem : Item
{
    public override string Name { get; set; } = "Subitem";
}
寄风 2025-01-02 18:38:12

一个可能的解决方案是使用属性并覆盖其 getter,如下所示:

public class Item
{
    public virtual string Name { get { return "Item"; } }
}
public class Subitem : Item
{
    public override string Name { get { return "Subitem"; } }
}

A possible solution would be to use a property and override its getter, like so:

public class Item
{
    public virtual string Name { get { return "Item"; } }
}
public class Subitem : Item
{
    public override string Name { get { return "Subitem"; } }
}
瞳孔里扚悲伤 2025-01-02 18:38:12

我遇到了与此类似的问题,其中成员变量本身就是相互继承的类对象。经过大量研究和修改,我想出了一个很好的解决方案。我在这里分享一下,希望对其他人有帮助。 (是的,我意识到这是一篇旧帖子,但因为它位于我的 google 搜索的顶部......)

我的目标是让 Unity 显示在编辑器为每个项目类别指定特定的统计数据类别。换句话说,当选择显示 WeaponStats 时,我想要一个武器对象,当选择显示 ArmorStats 时,我想要一个 Armor 对象,同时 Weapon 和 Armor 具有共享变量,WeaponStats 和 ArmorStats 也具有共享变量。

具体来说,我试图使用 new 关键字,以便派生类的变量(从基变量的类派生的类型)可以覆盖基变量(类类型)。然而

public class ItemStats {
    // variables like size, weight, etc
}

public class WeaponStats : ItemStats {
    // Additional variables like damage, rate of fire, etc
}

public class ArmorStats : ItemStats {
    // Additional variables like degree of damage reduction, etc

public class Item {
    public ItemStats stats;
    protected float degredation;
    // etc.
}

public class Weapon : Item {
    public new WeaponStats stats; // *The problem*
    protected Ammo ammo;
    // etc
}

public class Armor : Item {
    public new ArmorStats stats; // *Same problem*
    // etc
}

,这实际上并没有隐藏基本的 ItemStats 变量,而是隐藏了新的 WeaponStats 变量。同时也让我们对 Weapon 类中的变量 stats 所引用的内容感到非常头疼。
tldr这是一个坏主意。

在学习了更多关于继承的知识后,我最终想出的更好的解决方案是:

// Make the base class abstract, so each item has its own subclass.
// This avoids having two variables for stats, the problem I was trying to avoid.
public abstract class Item {
    public abstract ItemStats Stats();
    // notice that there is no ItemStats variable here anymore
    protected float degredation;
    // etc.
}

public class Weapon : Item {
    public WeaponStats stats;
    protected Ammo ammo;

    // This function lets other items interface with its stats.
    public override ItemStats Stats() {
        return stats;
    }
    // etc
}

// The same idea for Armor as for Weapon

这使得 Unity 的编辑器能够仅显示匹配的统计信息类(例如,带有武器的 WeaponStats 和带有 Armor 的 ArmorStats);为每个 Stats 类提供所有 ItemsStats 共有的继承变量;并且还允许所有项目知道其他项目具有统计数据。

希望这对其他人有帮助:)

I had a similar problem to this, where member variables were themselves class objects that inherited from each other. After a lot of researching and tinkering, I came up with a good solution for me. Here I am sharing it in the hope that it will help someone else. (And yes, I realize that this is an old post, but as it was at the top for my google searches . . .)

My goal was for Unity to show in the editor the specific stats class for each item category. In other words, I wanted a Weapon Object when selected to show WeaponStats, and an Armor Object when selected to show ArmorStats, all while Weapon and Armor had shared variables and WeaponStats and ArmorStats also had shared variables.

Specifically, I was trying to use the new keyword so that a base variable (of a class type) could be overridden by the derived class's variable (of a type derived from the base variable's class). As in:

public class ItemStats {
    // variables like size, weight, etc
}

public class WeaponStats : ItemStats {
    // Additional variables like damage, rate of fire, etc
}

public class ArmorStats : ItemStats {
    // Additional variables like degree of damage reduction, etc

public class Item {
    public ItemStats stats;
    protected float degredation;
    // etc.
}

public class Weapon : Item {
    public new WeaponStats stats; // *The problem*
    protected Ammo ammo;
    // etc
}

public class Armor : Item {
    public new ArmorStats stats; // *Same problem*
    // etc
}

However, this didn't actually hide the base ItemStats variable and instead hid the new WeaponStats variable. As well as creating a lot of headache about what variable stats was referring to in the Weapon class.
tldr it was a bad idea.

The better solution I finally came up with, after learning a lot more about inheritance, was this:

// Make the base class abstract, so each item has its own subclass.
// This avoids having two variables for stats, the problem I was trying to avoid.
public abstract class Item {
    public abstract ItemStats Stats();
    // notice that there is no ItemStats variable here anymore
    protected float degredation;
    // etc.
}

public class Weapon : Item {
    public WeaponStats stats;
    protected Ammo ammo;

    // This function lets other items interface with its stats.
    public override ItemStats Stats() {
        return stats;
    }
    // etc
}

// The same idea for Armor as for Weapon

This enabled Unity's Editor to only display the matching stats class (WeaponStats with Weapons and ArmorStats with Armor, for example); gave each Stats class inherited variables common to all ItemsStats; and also allowed all Items to know that other Items had stats.

Hope this is helpful to someone else :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文