C# 多态性属性

本文关键字:属性 多态性 | 更新日期: 2023-09-27 18:37:10

我有一个简单的问题。有一个基类产品。并派生出手镯、耳环和戒指等类别。但是环类有一个额外的属性。

我将如何达到该大小属性并在以下代码的方法中使用它。

public class Product
{
    public int id;
    public string title;
}
public class Bracelet : Product
{
}
public class Earring : Product
{
}
public class Ring : Product
{
    public int size;
}
Product product;
if(category = 1) // this is a  Bracelet
{
    product = new Bracelet();
}
else if(category = 2) // this is a Earring
{
    product = new Earring();
}
else if(category = 3) // Wola, this is a ring
{
    product = new Ring();
    product.size = 4; // I cant reach size.. I need to assign size of the ring to decrease stock correctly.
}
product.decreaseStock();

C# 多态性属性

只需先在本地声明值:

else if (category == 3) 
{
    var ring = new Ring();
    ring.size = 4;
    product = ring;
}

这样,您就可以将变量作为if块中的Ring访问,但它也会将其分配给更通用的product变量。

或者,您可以只使用初始值设定项语法:

else if (category == 3) 
{
    product = new Ring { size = 4 };
}

Kirk Woll 的答案可能是最好的,但另一种解决方案是使用 'as' 关键字:

(product as Ring).size = 4;

或投射它:

((Ring)product).size = 4;

此外,请确保不要将赋值运算符 (=) 与相等运算符 (==) 混淆。例如,它应该是 if(类别 == 3)

你将不得不覆盖 Ring 中的 reductionStock 方法。

因此,在产品中,首先将减少库存方法标记为虚拟。

public class Product
{
    public int id;
    public string title;
    public virtual void DecreaseStock()
    {
        //your decrease logic here
    }
}

然后在环中,在重写方法中考虑大小的新逻辑

public class Ring : Product
{
    public int size;
    public override void DecreaseStock()
    {
        //your special logic to deal with size here
    }
}

你最好通过 C# 阅读 Jeffrey Richter 的 CLR。

您不能通过引用来引用ring的属性product因为 CLR 不知道这个对象是环,这就是 CLR 不允许你更改其大小的原因。相反,您应该使用:

Ring ring = new Ring();
ring.size = 4;

如果要通过引用访问此属性product则应在基类中声明该属性。

在这种情况下,由于您在创建Ring后更改大小,因此要走的方法是将其作为Ring而不是Product来处理:

Ring ring = new Ring();
ring.size = 4;
product = ring;

如果我们有一个Product我们知道是我们可以投Ring的情况下。如果它实际上是Earring,这将导致运行时错误:

Ring ring = (Ring)product;
ring.size = 4;

或者更简洁地说:

((Ring)product).size = 4;

如果产品可能是Ring,也可能不是,并且我们想设置size如果是,我们当然可以测试:

if(product is Ring)
  ((Ring)product).size = 4;

通常,将测试和转换结合起来是明智的:

Ring ring = product as Ring;
if(ring != null)
  ring.size = 4;

很多选角是一个不好的征兆。一般来说,我们应该在我们关心的层面上处理一个对象——只有当我们只知道它是一个Product时,我们才做Product事情。可以帮助执行此操作的一件事是从重写访问方法或属性:

public class Product
{
  /* leave out other stuff */
  public virtual bool NeedsLargeBox
  {
    get
    {
      return false; // most products don't
      //(this property could also be abstract to force all derived
      //classes to decide upon how it operates)
    }
  }
}
public class Ring : Product
{
  public int size;
  public virtual bool NeedsLargeBox
  {
    get
    {
      return size > 100;
    }
  }
}

现在,当Ring本身处理size时,代码可以处理一堆Product对象,并决定有多少需要大盒子和多少小盒子,而这些代码不必直接访问size(甚至不知道它,它可以在创建之前编写和工作Ring)。