c#多态性属性

c#多态性属性,c#,polymorphism,C#,Polymorphism,我有一个简单的问题。 有一个基类产品。 以及衍生类别,如手镯、耳环和戒指。 但ring类有一个额外的属性 我将如何达到这个size属性,并在下面代码中的方法中使用它 public class Product { public int id; public string title; } public class Bracelet : Product { } public class Earring : Product { } public class Ring : Pr

我有一个简单的问题。 有一个基类产品。 以及衍生类别,如手镯、耳环和戒指。 但ring类有一个额外的属性

我将如何达到这个size属性,并在下面代码中的方法中使用它

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();

只需首先在本地声明该值:

else if (category == 3) 
{
    var ring = new Ring();
    ring.size = 4;
    product = ring;
}
通过这种方式,您可以在
if
块中以
的形式访问变量,但它也会将其分配给更通用的
产品
变量

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

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

只需首先在本地声明该值:

else if (category == 3) 
{
    var ring = new Ring();
    ring.size = 4;
    product = ring;
}
通过这种方式,您可以在
if
块中以
的形式访问变量,但它也会将其分配给更通用的
产品
变量

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

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

您将不得不重写环中的decreaseStock方法

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

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
    }
}

您将不得不重写环中的decreaseStock方法

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

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#阅读杰弗里·里希特的CLR

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

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

如果您想通过
product
引用访问此属性,则应在基类中声明它。

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

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

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

如果您想通过
产品
引用访问此属性,则应在基类中声明它。

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

(product as Ring).size = 4;
或是投下它:

((Ring)product).size = 4;

另外,请确保不要将赋值运算符(=)与相等运算符(=)混淆。例如,如果(category==3)

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

(product as Ring).size = 4;
或是投下它:

((Ring)product).size = 4;

另外,请确保不要将赋值运算符(=)与相等运算符(=)混淆。例如,如果(category==3)

在这种情况下,由于您刚刚创建了
,正在更改大小,因此方法是将其作为
处理,而不是作为
产品

Ring ring = new Ring();
ring.size = 4;
product = ring;
在一个案例中,我们有一个
产品
,我们知道我们可以铸造一个
戒指。如果它实际上是一个
耳环
,则会导致运行时错误:

Ring ring = (Ring)product;
ring.size = 4;
或者更简洁地说:

((Ring)product).size = 4;
如果产品可能是
环,也可能不是,我们想设置
大小,如果是,我们当然可以测试:

if(product is Ring)
  ((Ring)product).size = 4;
通常,将测试和强制转换结合起来是明智的:

Ring ring = product as Ring;
if(ring != null)
  ring.size = 4;
大量的演员阵容是个坏兆头。一般来说,我们应该在我们关心的层次上处理一个对象——只做
产品
的事情,而我们只知道它是
产品
。有一件事可以帮助做到这一点,那就是通过重写访问方法或属性:

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
,而代码可以处理一堆
产品
对象,并决定需要多少大盒子和多少小盒子,而无需代码直接访问
size
(或者甚至知道它,它甚至可以在
Ring
创建之前编写和运行).

在这种情况下,由于您在创建
环后立即更改了大小,因此要做的是将其作为
环来处理,而不是作为
产品来处理:

Ring ring = new Ring();
ring.size = 4;
product = ring;
在一个案例中,我们有一个
产品
,我们知道我们可以铸造一个
戒指。如果它实际上是一个
耳环
,则会导致运行时错误:

Ring ring = (Ring)product;
ring.size = 4;
或者更简洁地说:

((Ring)product).size = 4;
如果产品可能是
环,也可能不是,我们想设置
大小,如果是,我们当然可以测试:

if(product is Ring)
  ((Ring)product).size = 4;
通常,将测试和强制转换结合起来是明智的:

Ring ring = product as Ring;
if(ring != null)
  ring.size = 4;
大量的演员阵容是个坏兆头。一般来说,我们应该在我们关心的层次上处理一个对象——只做
产品
的事情,而我们只知道它是
产品
。有一件事可以帮助做到这一点,那就是通过重写访问方法或属性:

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
,而代码可以处理一堆
产品
对象,并决定需要多少大盒子和多少小盒子,而无需代码直接访问
size
(或者甚至知道它,它甚至可以在
Ring
创建之前编写和运行).

谁的saaid size与库存减少有关?@JonHanna是正确的,但如果每个对象都能处理好自己的属性,那就更好了,而不是
if,else if,else if
是的,如果可能的话,但并不总是如此。作者:我如何达到那个size属性并在下面代码中的方法中使用它。你说得对。滚动使我误入歧途:(saaid size与库存减少有什么关系?@JonHanna是正确的,但如果每个对象都照顾到自己的属性,而不是
if,else if,else if
Yes,如果可能的话,但并不总是如此。作者:我如何达到该size属性,并在下面代码中的方法中使用它。是的。滚动使我误入歧途:(最好提一下,您需要将
产品
投射到
以访问
si