Home > Software engineering >  How to run some code in a class at the time that it is defined?
How to run some code in a class at the time that it is defined?

Time:10-21

In Python, I can have the equivalent of C# static members:

class MyClass:
  i = 0  # This is like a C# static member

print(MyClass.i)

gives output

0

But maybe my static member needs to be calculated somehow. I can do:

class MyClass:
  i = 0
  i  = 10

print(MyClass.i)

gives output

10

In practice, I'm writing a config class which needs to read a json file from disk, validate it, and then populate some static members. The closest thing to what I want to do in Python would look like:

class GlobalConfig:
  with open('config.json', 'r') as f:
    config_dict = json.read(f)
  # Maybe do some validation here.
  i = config_dict["i"]
  a = config_dict["hello_world"]

Truth be told, I wouldn't really do this in Python, but I'm borrowing from C# in that everything needs to go in classes.

In practice in my C# code, I would have a GlobalConfig class in a Config.cs file and all my other files would have access to this.

But it seems I can't do anything other than declare/define members in the class body. How can I do the work of loading up and parsing my config file and have the result of that be accessible as static members to the rest of my program?

PS: I don't really want this to influence the answers I get in unless it has to, but FYI I am working with Unity.

CodePudding user response:

Are you looking for static constructor?

public class MyClass { 
  private static int i = 0;

  private static int j;

  private static int loadJ(int value) {...}

  // Static constructor will be called before the first MyClass call
  static MyClass() {
    // If you want to compute anything with static you can do it here
    i  = 10; 
    // you can call static methods here, address static fields and properties
    j = loadJ(i);
  }
}

CodePudding user response:

An alternative to static constrcutors is some lazy-loading approach. In essence you just initialize your class when it is used in any way calling the loading-function internally:

public class MyClass 
{ 
    static int i;
    private static int loadJ() 
    {
        i = ReadValueFromJson();
    }

    public static DoSomething()
    {
        // load if not yet done
        if(!loaded) 
            loadj();
        // do the actual work
    }
}

The advantage here is that you get more fine-grained controll about if or if not initialization should happen. Imagine some constant within your config-class that allways has the exact same value regardless of any initialization. The downsie is that you need to add this boilerplate to all the members that need loading.

  • Related