实现" Virtual Static"的好方法可以吗?使用简单的示例案例

时间:2017-09-24 15:52:26

标签: c# unity3d static polymorphism virtual

首先,让我明确一点,这不是虚拟静态无法解决的另一个问题,因此请不要回答编译器如何看待虚拟和静态,或将其标记为这些问题的副本,但如果你知道任何问题的答案符合我的例子,那么随时链接和标记重复。

现在,通过搜索如何实现本来可以解决的问题,有很多人说"我甚至不知道为什么你需要这样做"而那些试图像我一样提出同样问题的人的例子有很多不同的例子,所以我发现很难将其他人的答案联系起来。

所以,在这个游戏中,我想让我有一个简单的InventoryItem系统。每个Item都来自virtual class类可以识别的Inventory

public class Item {
    public virtual static Sprite getIcon();
    public virtual static string getName();
}

public class Stone : Item {
    static Sprite icon;
    static string name = "Stone";

    public override static Sprite getIcon(){
        return icon;
    }
    public override static string getName(){
        return icon;
    }

    // ...
}

所以我的想法基本上是每个Stone在你的icon中共享Inventory并且所有宝石都有相同的名称/标题,比如在调试消息中使用或给出播放一些他正在看或正在接受的信息。

现在我的所有胆量告诉我,最佳做法是Sprite应为static,因为StoneInventory的所有实例都应显示相同的icon Sprite 1}}。但是,所有类型的项目也应该有inherit,因此他们应get使用常见的get方法来检索这些项目。

因此,我提出的两种选择感觉常规错误或过于错误。

1)使static - 方法非 - string并使它们返回静态成员的内容。这是非常规的,因为它为每个实例的每个实例带来开销,其中返回值对于每个实例都是相同的。

编辑:更正,没有额外的开销,因此这种方法是可行的。

2)创建一个存储所有sprite /名称的master类,并根据给定对象的类型返回它们。首先,我不喜欢使用类型比较/检查,因为我觉得如果可以的话,最好避免这样做。但即便如此,我觉得这个解决方案对于返回Sprite$(document).ready(function() { var inputs = [""]; var totalString; var tempNum; var operators1 = ["+", "-", "/", "*"]; var operators2 = ["."]; var operators3 = ["%"]; var num = [1, 2, 3, 4, 5, 6, 7, 8, 9]; function getValue(input) { if (operators1.includes(inputs.length - 1) === true && inputs === ".") { alert("Duplicate '.' "); } else if (inputs.length == 1 && operators1.includes(input) === false) { inputs.push(input); } else if (operators2.includes(inputs[inputs.length - 1]) === false) { inputs.push(input); } else if (num.includes(Number(input))) { inputs.push(input); } update(); } function update() { totalString = inputs.join(""); $("#display").html(totalString); } function getTotal() { totalString = inputs.join(""); $("#display").html(eval(totalString)); } $("a").on("click", function() { if (this.id === "clearAll") { inputs = [""]; update(); } else if (this.id === "clearLast") { inputs.pop(); update(); } else if (this.id === "total") { getTotal(); } else if (this.id === "%") { tempNum = inputs.join(""); var percent = Math.floor(totalString * (tempNum / 100)); update(); } else { if (inputs[inputs.length - 1].indexOf("+", "-", "/", "*", ".")) { getValue(this.id); } else { getValue(this.id); } } }); }); 参考

等微不足道的任务来说太过分了。

因此,除非我遗漏了某些内容,否则没有直接的方法来实现这一目标?或者我的两种方法中的一种比我认为的更好?

PS:我要为Unity游戏实现这一点,所以如果团结提供解决方案,那么我全都是耳朵。

2 个答案:

答案 0 :(得分:1)

  

在罗马时,像罗马人一样。 :)

如果你使用C#,我建议避免使用Java风格的编码。

例如,方法名称采用PascalCase形式而不是camelCase形式,C#也有properties而不是getter / setter方法。所以这是我的建议:

public abstract class Item
{
    public abstract Sprite Icon { get; }

    public abstract string Name { get; }
}

public class Stone : Item
{
    private static readonly Sprite icon = Sprite.Create(/* parameters omitted */);

    private const string name = "Stone";

    // expression-bodied member: supported as of C# 6
    public override Sprite Icon => icon;

    // traditional propery getter
    public override string Name
    {
        get
        {
            return name;
        }
    }
}

你在这里可以看到:

  • 您可以覆盖标有abstractvirtualoverride关键字的属性和方法。我将Item类及其属性设为abstract,因此我不需要在Item类中实现属性,只能实例化Stone之类的派生类型。必须覆盖属性。
  • 由于icon字段的值不会更改,因此我也应用了readonly个关键字,因此无法更改。
  • name字段也可以是readonly,但我们使用static readonly string关键字代替const字段,这使得name字段不仅static但它的价值也无法改变。 请注意: static readonlyconst的行为有所不同,请参阅here
  • 重写的属性有两种形式:Name属性以传统的C#方式实现,Icon属性使用新的expression-bodied member功能实现。

总结一下,没有冒犯,我的目的只是为了展示你的解决方案如何在一个看起来不像Java的C#中实现。

答案 1 :(得分:0)

根据评论者的一些澄清,我发现我说的第一个解决方案实际上是我正在寻找的直截了当的答案。只需将变量设为静态,但继承/覆盖方法是非静态的,但使用它来检索静态值。

public class Item {
    public virtual Sprite getIcon();
    public virtual string getName();
}

public class Stone : Item {
    static Sprite icon;
    static string name = "Stone";

    public override Sprite getIcon(){
        return icon;
    }
    public override string getName(){
        return icon;
    }

    // ...
}