简体   繁体   中英

c# polymorphism property

I have a simple question. There is a base class Product. And derived classes as Bracelet, Earring and 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.

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.

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:

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

You're going to have to override the decreaseStock method in Ring.

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#.

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

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 = new Ring();
ring.size = 4;
product = ring;

In a case where we had a Product we knew was a Ring we could cast. This will cause a runtime error if it is in fact an 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:

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 . 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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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