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

Question Static variable that are shared between instances of a Single Concrete class, but not between concre

Discussion in 'Scripting' started by jGate99, Apr 3, 2023.

  1. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,844
    Hi there,

    I have a problem which Im having problem with and not sure whether Its doable in C# or not.

    I have a base class with a static variable, and I want 2 of its conrecte class to have "their own" view of that static variable, so all the instances of Concrete1 will share the same static variable of Concrete 1,
    but all the instances of Concrete2 will share Concrete2 static variable?

    Currently im definding the same code in both concrete classes, but is there a way i could define the static on base class and then get the above result?

    Please advise
     
  2. halley

    halley

    Joined:
    Aug 26, 2013
    Posts:
    1,863
    No, that isn't how it works.

    If Mammal had a static variable that is either public or protected, then Cat and Horse both have access to that static variable. Cat and Horse and Dog and Monkey can all declare their own static variables which are only visible to their respective classes.

    There is a 'new' keyword which would behave somewhat similar to what you propose, but I don't recommend it. If Mammal had a static variable, then Human could say it has a 'new' static variable reusing the base class's name. Human and its subclasses would not access or modify the base Mammal version of the variable without special care. The problem is it's really easy to accidentally access the wrong one, so it's a bug magnet. I feel it's meant as a stop-gap to work around conflicts later in a mature/legacy stage of an overengineered crusty codebase, and not as a feature you want to go basing intentional functionality upon.

    In your case, it sounds like you might need to compose a feature in, rather than inherit. Lots of animals have liver function, even if they don't all inherit it from a common ancestor. Create a specialized class which manages JUST the pseudo-shared capability, and then let them all inherit or implement an interface to use it.
     
    jGate99 and Kurt-Dekker like this.
  3. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    108
    There is a bit of a hack that you can do with generics.
    Code (CSharp):
    1. public class Mammal
    2. {
    3.      protected class MyInheritableStatic<T>
    4.      {
    5.           public static int x = 5;
    6.      }
    7. }
    8.  
    9. public class Human : Mammal
    10. {
    11.      void SomeFunc()
    12.     {
    13.           MyInheritableStatic<Human>().x += 1;
    14.      }
    15. }
    16.  
    17. public class Cow : Mammal
    18. {
    19.      void SomeFunc()
    20.     {
    21.           MyInheritableStatic<Cow>().x -= 1;
    22.      }
    23. }
    24.  
    25.  
     
    jGate99 and Bunny83 like this.
  4. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    108
    While something like this may satisfy the question asked, in practice it’s not very useful. This is the kind of thing that leads to confusing code and unique code structure problems.
    For example, would “ class Child : Human” want to modify the <Child> static var or the <Human> static var.

    Side note you will probably want to add a restriction to the generic to only accept classes of type Mammal.
    Code (CSharp):
    1. protected class MyInheritableStatic<T> where T : Mammal
    2. {
    3.      public static int x = 0;
    4. }
     
    jGate99 likes this.
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,848
    Does the value actually need to be static?

    You could just make a virtual/abstract property and override that in child classes.
    Code (CSharp):
    1. public abstract Animal
    2. {
    3.     public abstract int LegCount { get; }  
    4. }
    5.  
    6. public abstract Horse : Animal
    7. {
    8.     public override int LegCount => 4;
    9. }
    10.  
    11. public abstract Spider : Animal
    12. {
    13.     public override int LegCount => 8;
    14. }
    Not that you should generally code like this. As noted above, composition over inheritance.

    Otherwise this feels like an XY problem. What's the actual problem your trying to solve here?
     
    angrypenguin and Bunny83 like this.
  6. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,844
    Thank you very much
     
  7. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    Everything about this thread is terrifying... I really do suggest you listen to the person who wrote that hack when they said:
    I don't even see how this solves your problem considering that all you've done is moved your syntax.

    You say your issue arises from a desire to not have to write the same boiler plate in each child class:
    But like, sure, now you don't have to do this single line in every concrete class:
    Code (csharp):
    1. static int x;
    But... you now have to write this very oddly specific code any time you want to access it:
    Code (csharp):
    1. MyInheritableStatic<ConcreteType>.x = 5;
    Like what even is the point of that?
     
  8. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,524
    Also, this generic line you have to use every time essentially creates a new concrete type each time you use a different generic argument. Just that this type is compiler / runtime generated, but you still have to actually write it out explicitly. I also don't see the benefit here :)

    If the goal is to have an actual polymorphic static field across different concrete child classes, you can simply do
    Code (CSharp):
    1.  
    2. public abstract class Base
    3. {
    4.     public abstract int MyValue { get; set; }
    5. }
    6.  
    7. public class SomeChild : Base
    8. {
    9.     public static int TheActualStatic;
    10.     public override int MyValue
    11.     {
    12.         get => TheActualStatic;
    13.         set => TheActualStatic = value;
    14.     }
    15. }
    Now each child class would simply have its own static field but you can also access it polymorphically through the MyValue property.
     
    jGate99, lordofduct and spiney199 like this.
  9. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,844
    Thanks, I have now moved to child classes as you described
     
    DouglasPotesta likes this.
  10. DouglasPotesta

    DouglasPotesta

    Joined:
    Nov 6, 2014
    Posts:
    108
    Awesome. Thanks for updating. Im sure some of us will be able to sleep better knowing that.
     
  11. MartinMa_

    MartinMa_

    Joined:
    Jan 3, 2021
    Posts:
    455
    This whole thread looks like you want invent your own instances system even if instances are already invented just with no static variables. This really doesn't make any sense for me.