简体   繁体   English

c#多态性

[英]c# polymorphism property

I have a simple question. 我有一个简单的问题。 There is a base class Product. 有一个基类产品。 And derived classes as Bracelet, Earring and Ring. 派生类为Bracelet,Earring和Ring。 But ring class has an extra property. 但是铃声类具有额外的属性。

How am I going to reach that size property and use it in a method in below code. 我将如何达到该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();

Just declare the value locally first: 只需先在本地声明值:

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

This way, you have access to the variable as a Ring within your if block, but it also assigns it to the more general product variable too. 这样,您就可以在if块中以Ring访问变量,但也可以将其分配给更通用的product变量。

Alternatively, you can just use initializer syntax: 另外,您可以只使用初始化程序语法:

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

Kirk Woll's answer is probably best, but an alternate solution would be to use the 'as' keyword: 柯克·沃尔(Kirk Woll)的答案可能是最好的,但是另一种解决方案是使用'as'关键字:

(product as Ring).size = 4;

or to cast it: 或将其投放:

((Ring)product).size = 4;

Also, make sure you don't confuse the assignment operator (=) with the equality operator (==). 另外,请确保不要将赋值运算符(=)与相等运算符(==)混淆。 It should be, for example, if(category == 3) 例如,应该为if(category == 3)

You're going to have to override the decreaseStock method in Ring. 您将不得不在Ring中重写reduceStock方法。

So, in product, first mark the decrease stock method as virtual. 因此,在产品中,首先将减少库存的方法标记为虚拟。

public class Product
{
    public int id;
    public string title;

    public virtual void DecreaseStock()
    {
        //your decrease logic here
    }
}

Then in ring, put your new logic that takes size into account in your override method 然后,在覆盖方法中放入考虑大小的新逻辑

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

You better read Jeffrey Richter's CLR via C#. 您最好通过C#阅读Jeffrey Richter的CLR。

You can't refer to ring 's property by product reference, because CLR wouldn't know that this object is ring, and that's why CLR won't allow you to change it's size. 您不能通过product引用来引用ring的属性,因为CLR不会知道该对象是ring,这就是为什么CLR不允许您更改其大小。 Instead you should use: 相反,您应该使用:

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

If you want to reach this property via product reference it should be declared in base class. 如果要通过product引用访问此属性,则应在基类中声明它。

In this case, since you are altering the size just after you've created the Ring , the way to go is to deal with it as a Ring rather than as a Product : 在这种情况下,由于您是在创建Ring后立即更改尺寸的,因此,解决方法是将其作为Ring而不是作为Product来处理:

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

In a case where we had a Product we knew was a Ring we could cast. 在我们拥有Product的情况下,我们知道是可以铸造的Ring This will cause a runtime error if it is in fact an Earring : 如果实际上是Earring则将导致运行时错误:

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

Or more concisely: 或更简而言之:

((Ring)product).size = 4;

In cases where the product might be a Ring and might not, and we want to set size if it is, we can of course test: 如果产品可能是Ring ,可能不是Ring ,并且如果我们想设置size ,我们当然可以测试:

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

Often it's sensible to combine the test and cast: 通常将测试和强制转换结合在一起是明智的:

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

A lot of casting is a bad sign. 大量投放是一个不好的信号。 Generally, we should be dealing with an object at the level we care about - only doing Product things when all we know is that it is a Product . 通常,我们应该在我们关心的级别上处理对象-仅当我们知道它是Product时才执行Product事情。 One thing that can help do this is by accessing the method or property from an override: 可以帮助实现此目的的一件事是通过重写来访问方法或属性:

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

Now while Ring itself deals with size , code could process a bunch of Product objects and decide how many needed large and how many small boxes, without that code having to access size directly (or even know about it, it could be written and working before Ring was even created). 现在,当Ring本身处理size ,代码可以处理一堆Product对象并确定需要多少个大盒子和多少个小盒子,而该代码不必直接访问size (甚至不知道size ,就可以在之前编写和运行它甚至创建了Ring )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM