16

How to write static constructor in Dart?

class Generator
{
   static List<Type> typesList = [];

   //static
   //{ /*static initializations*/}

}
Arif
  • 215
  • 1
  • 4
  • 10

8 Answers8

16

There is no such thing as a static constructor in Dart. Named constructors such as Shape.circle() are achieved by something like

class A {
  A() {
    print('default constructor');
  }
  A.named() {
    print('named constructor');
  }
}

void main() {
  A();
  A.named();
}

You might also be interested in this factory constructors question

Update: A couple of static initializer work-arounds

class A {
  static const List<Type> typesList = [];
  A() {
    if (typesList.isEmpty) {
      // initialization...
    }
  }
}

Or the static stuff can be moved out of the class if it isn't meant to be accessed by users of the class.

const List<Type> _typesList = [];
void _initTypes() {}

class A {
  A() {
    if (_typesList.isEmpty) _initTypes();
  }
}
Jacob Phillips
  • 8,841
  • 3
  • 51
  • 66
  • 2
    thanks Jacob. it seems that Dart is still in development stage,, lacking features what i found in java, is an unpleasing experience, or may by i am very new to Dart... – Arif Jan 20 '20 at 04:17
  • 1
    @arif Dart is pretty mature imo. It doesn't have static initializer blocks like Java, but there are other ways of achieving the same thing. In my experience it can do everything Java can, and is usually more concise. I mean there are differences, nested classes are not supported for example. – Jacob Phillips Jan 20 '20 at 12:43
  • When the other ways include things like running code generators before building the program, it's not quite as having the same features. Though I suppose some of that is to achieve some ahead of time compilation advantages. A class doesn't get "loaded" in release dart code. Similarly if you make a global variable, it might not get initialized before it's accessed, so it doesn't seem to be possible to create a system where at runtime the 'class' registers itself to another class as existing(or not) without generated code. – Lassi Kinnunen Mar 08 '23 at 17:01
  • One reason to not allow this might be avoiding 'static initialization order fiasco' (dependency of a static initializer on another static initializer where the order of initialization is not guaranteed). C++ is prone to this but also Java araccording to https://stackoverflow.com/a/6606783/288875. – Andre Holzner May 19 '23 at 18:46
8

You can initialize static members by calling the class.member directly, inside the constructor:

class A {
  static int a;
  static int b;

  A(int a, int b) {
    A.a ??= a; ///by using the null-equals operator, you ensure this can only be set once
    A.b ??= b;
  }
}


main(){
  A(5,10);
  A(2,4);
  assert(A.a == 5);
  assert(A.b == 10);
}
E_C
  • 300
  • 2
  • 10
  • thanks E_C. Dart should provide some way. This approach is instance dependent. – Arif Jan 20 '20 at 04:21
  • This is true. However, due to the nature of static members, it doesn’t matter much, as you can see in my example, even though there are 2 instances, only the first made a difference. But, as Jacob alluded to, factory constructor’s seem to be what you are looking for. They do not need to create a new instance. Also, constant constructor’s will only ever create one instance. Check out : https://dart.dev/guides/language/language-tour#using-constructors and https://dart.dev/guides/language/language-tour#constant-constructors – E_C Jan 20 '20 at 04:28
2

Inspired by @Mahmoud salah eldien saber answer Create a singleton, and static variable reference to the singleton variable

void main() {
  
  print('${Singleton.add()}');
  print('${Singleton.add()}');
  print('${Singleton.add()}');
  print('${Singleton.add()}');     
}

class Singleton {
  Singleton();
    
  //static
  static List<int> typeList = Singleton.internal()._typeList;
  static List<int> add() {
    typeList.add(1);
    return typeList;
  }  
  List<int> _typeList = [];
  factory Singleton.internal() {  
    var s = Singleton();
    for(int i = 0 ; i < 5; i++ ) {
      s._typeList.add(2);
    }   
    return s;
  }    
   
}

I also want to find a official answer for this question.

1

Static variable declarations are initialized lazily to avoid costly initialization (and attendant slowness) at program startup.. The first time a static variable v is read, it is set to the result of evaluating its initializer.

https://groups.google.com/a/dartlang.org/forum/#!topic/misc/dKurFjODRXQ

Arif
  • 215
  • 1
  • 4
  • 10
1

One of the workarounds to initialize static variables could be to use ".." (called "cascade") operator. This workaround doesn't require object instance. More about cascade operator: https://dart.dev/guides/language/language-tour#cascade-notation .

Example:

static List firstList = [ 'hello', 12, 'goodbye'];

static List dummyObjects = List()
    ..addAll(firstList)
    ..add('another String value')
    ..add('and one more')
    ..add(Object())
    ..removeWhere((o) => o is! String)
;

(So dummyObjects is initialized only with objects that are of type String because all others discarded.)

1

static initialization block

In Dart there is no equivalent to the Java static initialization block.
However, an easy workaround for most cases is extracting the static initialization logic to a static function.

class Dummy {
  static final Map<int, String> someValues = _createSomeValues();

  static Map<int, String> _createSomeValues() {
    Map<int, String> someValues = {};
    for (var i = 0; i <= 10; i++) {
      someValues[i] = "$i";
    }
    return someValues;
  }
}

Note that the static variable is initialized lazily as described in https://groups.google.com/a/dartlang.org/forum/#!topic/misc/dKurFjODRXQ. However, this behavior should never impact you with normal/clean code.

static method as factory

If you meant named constructors by 'static constructor' take a look at the following answer: https://stackoverflow.com/a/59811076/1218254

Thomas
  • 650
  • 9
  • 9
0

To create static (constuctor or class) it's very easy in dart, just create static vaiable in this class and give it object from the same class:

class A {
  static var instance = A();
  static List<int> typesList = [];
  A() {
    print('Call constructor to create object');
  }
  List<int> add() {
    typesList.add(1);
    return typesList;
  }
}

void main() {
  print(A.instance.add());
  print(A.instance.add());
  print(A.instance.add());
  print(A.instance.add());
}
Mahmoud Salah Eldin
  • 1,739
  • 16
  • 21
0

You could use a static method like this:

class A {
  A() {
     print('normal constructor');
  }

  static A fromValue(String value){
     ... //use your value
     return A();
  }


}

void main() {
  final a = A.fromValue('myValue');
}
C. Kontos
  • 1,198
  • 12
  • 21