Search Unity

Implementation of inherited class's function?

Discussion in 'Scripting' started by leegod, Sep 3, 2015.

  1. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,476
    Hi.

    So I have following codes,

    Code (CSharp):
    1. public abstract class Abs
    2. {
    3.     public virtual void DoSome()
    4.     {
    5.     }
    6. }
    7. [System.Serializable]
    8. public class SomeClass : Abs
    9. {
    10.     public string name;
    11.     public int number;    
    12. }
    13. ....
    14. public List<SomeClass> myClasses= new List<SomeClass>();
    15.  
    So lets say I need 10 concrete 'SomeClass' objects and put it to myClasses.

    Also I want manipulate SomeClass's fields at unity inspector,

    And each concrete 'SomeClass' 's DoSome() function should have different implementations.

    Then how can I implement those each DoSome() function?

    Thanks.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Not exactly sure what this statement means. Are you asking something???

    Well, 'SomeClass' is going to have to be serializable, so flag it as such. And the fields that you want to manipulate also need to be serializable (the types that you want to modify), so make sure that is so.

    If then the list 'myClasses' is a member of a MonoBehaviour type that is attached to a GameObject. The inspector will show an array property called 'My Classes', and you'll be able to resize the array and modify the objects.

    Oh... umm... just going to point out, saying 'myClasses' is a bit of a slip of the language. Those objects in the List aren't classes. They're objects of type 'SomeClass'. To say 'myClasses' would be if you had 10 accountants in a room, and you referred to the room as being "full of job titles".

    Nope, can't do that. Each 'DoSome' having a different implementation means its a different class.

    Now of course there's a way to make actions a composited component object that is attached to SomeClass so that it is configurable.

    But really, that's technically what MonoBehaviour is for... hence why we call them 'Components'.

    Seeing as you can't, this question can't actually be answered.
     
  3. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,476
    Yes it can't be via my original approach.

    But I solve myself like,

    Code (CSharp):
    1. public abstract class Abs
    2. {
    3.     public string name;
    4.     public int number;  
    5.     public virtual void DoSome(){}
    6. }
    7. [System.Serializable]
    8. public class SomeClassA : Abs
    9. {
    10.     public override void DoSome(){}
    11. }
    12. public class SomeClassB : Abs
    13. {
    14.     public override void DoSome(){}
    15. }
    16. ....
    17. public List<Abs> myClasses= new List<Abs>();
    18. public SomeClassA myA = new SomeClassA();
    19. public SomeClassB myB = new SomeClassB();
    20. ...
    21. myClasses.Add(myA);
    22. myClasses.Add(myB);
    23. ....
    24.  
    25. foreach(Abs a in myClasses)
    26. {
    27.       a.DoSome();
    28. }
    29.  
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Yes, that would work, because no longer are they all 'SomeClass', but instead they're all individual SomeClass.

    This to is a wonderful place for interfaces, rather than abstract classes, especially if the abstract class does nothing but define the methods that can be implemented. This way types that are already something else can ALSO be 'IAbs'.
     
  5. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,476
    Why in this case, [if the abstract class does nothing but define the methods], interface is better than abstract class?
     
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Because you can implement multiple interfaces.

    The downside is Unity doesn't serialise interfaces. So abusing abstract base classes is a common pattern in Unity.
     
  7. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,476
    Thanks for replies,

    And I met another issue.

    How can I use 'Instantiate' keyword within abstract class that is not inherited from MonoBehaviour?

    If I make abstract class inherited from MonoBehaviour, concrete class's fiield can't be manipulated via unity inspector.

    Code (CSharp):
    1. public abstract class Abs
    2. {
    3.     public string name;
    4.     public int number;
    5.     public virtual void DoSome()
    6.     {
    7.         GameObject gene = (GameObject)Instantiate(genObj, genPos.position, Quaternion.identity);
    8.     }
    9. }
    (got error if Abs does not inherited from MonoBehaviour)
     
  8. cowtrix

    cowtrix

    Joined:
    Oct 23, 2012
    Posts:
    322
    UnityEngine.Object.Instantiate() should work without you needing to inherit Abs from Monobehaviour.
     
  9. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    Note, yes, unity won't serialize a field that is typed an interface:

    Code (csharp):
    1.  
    2. public class SomeBehaviour : MonoBehaviour
    3. {
    4.  
    5.    public ISomeType obj; //this field will NOT be serialized
    6.  
    7. }
    8.  
    But, furthermore, the field won't be serialized to the object in the field, if the type is some base class of it:

    Code (csharp):
    1.  
    2. public class SomeBehaviour : MonoBehaviour
    3. {
    4.  
    5.    public Abs obj = new SomeClassA(); //this object will get serialized as Abs
    6.  
    7. }
    8.  
    When SomeBehaviour gets deserialized, obj will no longer be a SomeClassA, it will be an 'Abs'. All data and stuff related to SomeClassA will be lost.

    And also, because Abs is abstract, it'll actually have an error when it deserializes.


    There is an exception to this. If Abs inherits from MonoBehaviour, than its considered a UnityEngine.Object. These will be serialized by reference. BUT, it also means that you must attach the SomeClassA or SomeClassB to a GameObject somewhere and than attach the reference to it through the inspector (or by code).

    This gets into the big differences between how unity treats regular .net objects (managed objects), and unity objects (unmanaged objects created in unity, and only get a managed object in .net/mono for intercommunicating with the unmanaged object).
     
    Kiwasi likes this.