-3

Suppose you have a class relation like this:

class Banana : Fruit { }

If there are some public global values already assigned to fruit, is there a way to have a new banana class inherit these existing values?

For example:

class Fruit
{
   public int price;
   public string origins;
}

class banana : fruit
{
    public string peelDensity; 

    public Fruit (peelDensity p, int pr, string o)
    {
        peelDensity = p; 
        price = pr; 
        o = origins;
    }
}

Say an existing fruit instance already has its price, origins and etc assigned. Suppose that is actually common fruit data that applies to a particular banana. How would the banana inherit these values?

Is there a better way to do this than needing to supply all the existing values in the constructor?

banana b = new banana(peel, price, origins);

Is there a way to do something like this for a copy constructor:

public Banana(Fruit fruit){ this = fruit; }

The above is just some pseudocode. In my project, my Fruit class already has over 20 values assigned and the Banana class should inherit all of that, but I would like to figure out if there is a better way to write a more elegant constructor class.

ina
  • 19,167
  • 39
  • 122
  • 201
  • It can't inherit that. You will need to copy them over (factory method maybe?) – Nkosi Jul 30 '18 at 00:16
  • 1
    I am struggling to understand your question. Could you provide a [mcve] showing how you are populating the values? Also please specify the results you expect (but aren't getting). – mjwills Jul 30 '18 at 00:19
  • @nkosi do you mean i should assign all the existing values in fruit manually in a constructor for banana? – ina Jul 30 '18 at 00:26
  • 1
    @DavidG i'm learning how to code on my aunt's computer. please don't be mean. we are all learning something new everyday. – ina Jul 30 '18 at 00:27
  • Read the answer here: https://stackoverflow.com/questions/16534253/c-sharp-converting-base-class-to-child-class – Jim Berg Jul 30 '18 at 00:30
  • @davidg i don't want to get anyone in trouble. i'm just trying to ask a question i can't find online. i'm 7 years old. my parents don't want me to have an email address till i am 12 years old. this site won't let me sign up, but i am trying to figure out oop. i don't want to wait 5 years to figure this out. if you guys won't let me ask questions here, that's fine. i will try to find somewhere else. – ina Jul 30 '18 at 00:36
  • I'm sorry if I sounded mean, I'm just telling you the site rules. It's amazing that you're doing this as a 7 year old, I'm struggling to believe that you are so young! But maybe you should get some help from your aunt? – DavidG Jul 30 '18 at 00:38
  • 1
    @ina - C# doesn't have "public global values". It sounds like you're not quite getting what inheritance means. Inheritance just extends the definition of the class - it doesn't extend existing instances. `banana` doesn't extend an existing instance of `fruit`. `banana` extends the definition of `fruit` only. – Enigmativity Jul 30 '18 at 01:07

4 Answers4

1

There are two common ways to do this, by using a copy constructor and a factory approach.

Copy constructor:

public Banana(Fruit fruit)
{
    Price = fruit.Price;
    Origin = fruit.Origin;
}

Fruit apple = new Fruit(50, "some origin");
Banana banana = new Banana(apple);

Factory approach:

public static class FruitFactory
{
    public static Banana BananaFromFruit(Fruit fruit)
    {
        return new Banana(fruit.Price, fruit.Origin);
    }
}

Fruit apple = new Fruit(50, "some origin");
Banana banana = FruitFactory.BananaFromFruit(apple);

Notice that I corrected the casing of the classes and their properties to follow c# conventions.

Camilo Terevinto
  • 31,141
  • 6
  • 88
  • 120
  • Is there a way to automate the Copy Constructor? In my case, my base class has over 20 values that are already assigned. – ina Jul 30 '18 at 00:55
  • I think i want to do something like this `public Banana(Fruit fruit){ this = fruit; }` – ina Jul 30 '18 at 00:57
  • @ina The posted way is the fastest at run-time. A faster way of doing this at coding-time would be to use Reflection to copy the properties dynamically. I can add an example but that's going far from standard OOP – Camilo Terevinto Jul 30 '18 at 00:58
  • Creating a factory class is a huge waste of time for a simple task that should be done at the banana level. Using a constructor forces you to create a new banana even though fruit may already be a banana. – Jim Berg Jul 30 '18 at 01:01
  • @jimberg can you give an example? – ina Jul 30 '18 at 01:10
  • Yes. Look for the answer I posted. – Jim Berg Jul 30 '18 at 01:13
  • @JimBerg The Factory method follows the Separation of Concern principle and I don't see how defining a class can be considered a "huge waste of time". Your answer is far from what the OP wants anyway (they *know* they don't have a `Banana` instance, the check is useless) – Camilo Terevinto Jul 30 '18 at 01:15
  • @Camio Terevinto A Banana can't be concerned with the conversion of Fruit to a Banana? The static method essentially does what your constructor method does, but is much cleaner. It also allows a Banana to be a Banana factory. Are human being designed wrong? Should we have human being factories having the babies instead of human beings? ;-) Defining a static class to do a single thing that another class can already do is a waste of time. Yes. It also clutters the code base. Maybe the OP knows that the fruit is only a fruit, but you shouldn't really need to know that. – Jim Berg Jul 30 '18 at 01:30
  • @JimBerg The problem starts when you have more than one conversion. Some people like factories so the models are POCOs, other people like to have it all together in the models. Fortunately, it's all a matter of taste. (I wouldn't have a factory class for a single method like above, though) – Camilo Terevinto Jul 30 '18 at 01:37
  • @Camilio Terevinto, I agree. The Convert class is a perfect example of a factory doing conversions of unrelated types. In this case, it just makes more sense to encapsulate it within the class definition itself. When you've been at this as long as I have, you learn to develop for the moment and not for what you think you might need. If you write good code, you can refactor it easily for any new need that arises. Trying to adhere to certain arbitrary principles sometimes makes that difficult. – Jim Berg Jul 30 '18 at 02:05
1

You could do something like this:

public class Fruit
{
    public int Price { get; set; }
    public string Origins { get; set; }
}

public class Banana : Fruit
{
    public string peelDensity;

    public static Banana AsBanana(Fruit f)
    {
        return f as Banana ?? new Banana { Price = f.Price, Origins = f.Origins };
    }
}

The static method allows to return a Fruit as a Banana. If it's already a Banana being stored in a variable typed as a Fruit, it will be returned as a Banana. If not, a new Banana will be created with the values copied over.

If you want to convert a Fruit to a Banana, just call it like this:

Banana b = Banana.AsBanana( myFruit);

A Banana can always be assigned to a variable that is declared as a Fruit, but not vice versa. That's one of the major points about Object Oriented development.

Jim Berg
  • 609
  • 4
  • 7
0

As I understand your question I think you're pertaining to this:

This is your base class

public class Fruit{
     public double Price { get; set; }
     public string Origins { get; set; }

     //or you can create a constructor
     //one default constructor
     public virtual void GetPrice()
     {
          Price = 69;
     }
}

This is your child class:

public class Banana : Fruit{
     public string peelDensity { get; set; }    


      //this is a sample of Default Constructor
     public Banana()
            :base()
     {
          Price = 0; //here you're setting default value to banana once it's initialized
     }
     public override void GetPrice()
    {
          //base.GetPrice(); //here you get the value from the Parent Class 
            Price = 100; // here you're setting a value for the price of Banana once you call this method;
    }
}

Just to add some tips, since your Fruit class is very general, you can set it as an Abstract Class (collection of abstract methods that you can inherit with its child classes) but there are many ways you can abstract class for, and just set default values to your constructor if needed.

JC Borlagdan
  • 3,318
  • 5
  • 28
  • 51
  • Why would I call GetPrice method if Price is publicly available to me? – Chetan Jul 30 '18 at 00:53
  • I did it that way just to show how Inheritance will come to work when you need it (coz i got confused at first about your question). well i guess you got your answer there – JC Borlagdan Jul 30 '18 at 01:55
0

An other way as @JC Borlagdan mentioned is to create a Banana Factory which in turn creates Banana objects that have certain properties preset. You then have a separate factory for each inheritance that takes care of the default properties.

You can simply google the factory pattern. There are plenty of examples and explanations.

The factory can also be a method and does not have to live in a class. Here is a small example:

class BananaFactory {

    public int price;
    public string origins;

    Banana CreateBanana() {
        return new Banana(){
            peelDensity = "SomeValue",
            price = price,
            origins = origins
        };
    }
}


var banana = bananaFactoryinstance.CreateBanana();

// banana has price and origins that are set in the factory 
Oliver Heil
  • 62
  • 1
  • 9