Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Trouble with polymorphism

Discussion in 'Scripting' started by pazonkey, Oct 8, 2023.

  1. pazonkey

    pazonkey

    Joined:
    Oct 3, 2019
    Posts:
    1
    Hello everyone! I'm trying to make a beekeeping simulator but I'm having some trouble with polymorphism. I want different species of bees (honey, carpenter, miner) to harvest different types of items (nectar, wood, rock), with all those items being able to be stored in one inventory.

    So far I have class Item

    Code (CSharp):
    1. public class Item
    2. {
    3.     public string name;
    4.     public Sprite sprite;
    5.  
    6.     public virtual void SetName(){}
    7.  
    8.     public void SetSprite(){}
    9.  
    10.     public virtual void DepositItem(BeeController bee, HiveController hiveController)
    11.     {
    12.         hiveController.otherInventory.Add(this);
    13.         bee.inventory.Remove(this);
    14.     }
    15.  
    16. }
    17.  
    and Nectar, inheriting from Item

    Code (CSharp):
    1. public class Nectar : Item
    2. {
    3.     public Colors color;
    4.     public int stamina;
    5.  
    6.     public override void SetName()
    7.     {
    8.         name = color.ToString() + " Nectar";
    9.         Debug.Log(name);
    10.     }
    11.  
    12.     public override void DepositItem(BeeController bee, HiveController hiveController)
    13.     {
    14.         hiveController.nectarInventory.Add(this);
    15.         bee.inventory.Remove(this);
    16.     }
    17.  
    18.     public void DrinkNectar(BeeController bee)
    19.     {
    20.         bee.currentStamina += stamina;
    21.         if(bee.currentStamina > 100){bee.currentStamina = 100;}
    22.     }
    23.  
    24. }
    25.  
    Then I have an abstract class

    Code (CSharp):
    1. public abstract class ItemController
    2. {
    3.  
    4.     public abstract Item GetItem();
    5. }
    6.  
    which is to be inherited by the different object types the bees can interact with, IE this FlowerController

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5.  
    6. public class FlowerController : ItemController
    7. {
    8.  
    9.     public Nectar item;
    10.     public Colors color;
    11.     public int stamina;
    12.     public FlowerSO flowerSO;
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         item = new Nectar("Nectar");
    17.         item.color = color;
    18.         item.stamina = stamina;
    19.     }
    20.  
    21.     public override Nectar GetItem()
    22.     {
    23.         return item;
    24.     }
    25. }
    26.  
    But this gives me the following error

    Assets\Scripts\FlowerController.cs(21,28): error CS8830: 'FlowerController.GetItem()': Target runtime doesn't support covariant return types in overrides. Return type must be 'Item' to match overridden member 'ItemController.GetItem()'


    I thought that the whole point of my inheritance here is that items of class Nectar are ALSO of class Item. There must be some other way to declare things to get the result I want but I can't figure it out. Thanks for reading, I know it's a bit of a wall of text but I wanted to make sure to include all the details.
     
  2. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,355
    The problem is that Item is not always Nectar.

    I can't write code that generically uses an ItemController unless I know what GetItem returns. It needs to work the same regardless of what the inherited type is, or there is no point in having a base class in the first place.
     
  3. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,843
    You can't override a method and return a different type of value. Your
    GetItem()
    method needs to return an instance of type
    Item
    .

    The point of polymorphism is to allow derived types to be treated as their parent type. But your base type can be any number of derived types, potentially.
     
    Nad_B and APSchmidtOfOld like this.
  4. sergienko88

    sergienko88

    Joined:
    Jul 22, 2013
    Posts:
    22
    Try this:

    Code (CSharp):
    1.  
    2. public abstract class ItemController<T> where T: Item
    3. {
    4.     public abstract T GetItem();
    5. }
    6.  

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class FlowerController : ItemController<Nectar>
    7. {
    8.     public Nectar item;
    9.     public Colors color;
    10.     public int stamina;
    11.     public FlowerSO flowerSO;
    12.     // Start is called before the first frame update
    13.     void Start()
    14.     {
    15.         item = new Nectar("Nectar");
    16.         item.color = color;
    17.         item.stamina = stamina;
    18.     }
    19.     public override Nectar GetItem()
    20.     {
    21.         return item;
    22.     }
    23. }
    24.  
     
    Nad_B likes this.