In Java, we can use the instance initialization block to keep track of count of any class objects.
So, in dart how can we do that for a class with const Constructor?
I know that for a non-constant Constructor, we can achieve that by creating a static variable then incrementing its value in Constructor body.
But as we know that, const Constructor can't have a body, then how to keep track of number of instances created for a particular class ?
There can only be one instance of a class made with a const constructor. The one instance is instantiated during compilation, and all const calls to the constructor return it.
If you want to count the number of times a const constructor is used in a non-const context, this is not possible, because code with the potential to be executed during compilation cannot cause runtime side-effects.
Consider using a factory constructor for this purpose, like so:
class MyClass {
static var _instances = 0;
const MyClass();
factory MyClass.tracked() {
++_instances;
return const MyClass();
}
}
Not only can a (generative, non-redirecting) const constructor not have a body, it also cannot run any code with a side-effect. That's by design, so there is no way around it.
There really is no way, inside the language and program, to count instances of that class.
Using the developer tools is the only viable approach, because it can scan the actual runtime memory and see how many instances exist.
Related
I've been trying to implement a state management project for my design patterns course. I have implemented the singleton because I know that's essential for keeping state of a class. What I would like to do is: Create a general class, so that others could use it in their projects. How do I do that? My code so far:
class StateManager{
static final StateManager _instance = StateManager._singleton();
StateManager._singleton();
factory StateManager(){
return _instance;
}
}
My other solution to try and make it general:
class AppProvider extends StateManager<AppProvider>{
int i = 10;
String data = "adas";
}
class StateManager<T extends AppProvider>{
static final StateManager _instance = StateManager._singleton();
StateManager._singleton();
factory StateManager(){
return _instance;
}
}
I want the AppProvider class to be the client class, and I want the StateManager to automatically handle the fact that AppProvider should be a singleton, and maintain the state of AppProvider.. I really don't know how to do that.
Forcing a class to be a singleton through inheritance alone is not going to work. That's not something that the language supports. Constructors are not inherited, neither are static members, and you need those to access the singleton.
In order to be able to create an instance of a class at all, the class needs a generative constructor.
That generative constructor will create a new instance every time it's invoked, because that's what generative constructors do.
For a subclass to be able to extend a class, the superclass must have an accessible generative constructor too, but at least the superclass can be made abstract.
In order to force a class to be a singleton (if you really want that, because a singleton is really something of an anti-pattern; it makes the class act like it's just a bunch of global variables, and that makes testing harder), each such class needs to have a public static way to access or create the instance, and a private generative constructor.
So, basically, your first approach does what is needed, and since the constructors are not inherited, you need to do that for every singleton class, and there is nothing useful to inherit.
So, there is nothing you can do with inheritance to make singleton-ness be inherited, and you can't even help because everything a singleton needs is static.
A different approach is to make the state classes entirely private, so you don't have to worry about someone else creating instances, and give them a constant generative constructor each, and then only refer to them using const _ThisState() or const _ThatState().
This puts the responsibility on the user (you!) to only create one instance of each state object, but it also gives a very easy way to do that, because const _ThisState() will provide the same instance every time.
Or use the enum pattern, and have:
abstract class State {
static const State thisState = const _ThisState();
static const State thatState = const _ThatState();
const State._();
void handle(Context context, Object argument);
}
class _ThisState implements State {
const _ThisState();
void handle(Context context, Object argument) { ... }
}
class _ThatState implements State {
const _ThatState();
void handle(Context context, Object argument) { ... }
}
and then just refer to the state instances as State.thisState. I find that more readable than creating instances of seemingly unrelated classes.
I am trying out the new Dart FFI in making wrappers for libsodium. Libsodium needs to be initialized with calling init(). But I don't think the user should be burdened to remember this and I also wouldn't like to check some global state variable.
I know that Go has package init() functions which run when a package gets included. Is there something similar in Dart?
Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.
Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.
You could have a singleton instance and expose library functions as methods on the instance, and you could provide a public getter function that automatically does initialization.
For example, something like:
Libsodium? _instance;
Libsodium get libsodium => _instance ??= Libsodium._();
class Libsodium {
Libsodium._() {
// Do initialization.
}
void foo() {
// ...
}
void bar() {
// ...
}
}
and then callers would need to use it via:
import 'libsodium.dart';
libsodium.foo();
This would hide the class instantiation and wouldn't look any different to callers than if you were to use only top-level functions with a namespace (import 'libsodium.dart' as libsodium).
Dart does not have any way to implicitly run code. No code runs before main, and all code running after main does so because it was invoked directly or indirectly from the main method. So, no.
If you need something initialized, there is a number of options.
You can use a lazily initialized static variable:
var _initialState = _init();
int doSomething(arguments) {
_initialState;
do the something.
}
The reading of _initialState will ensure that init is invoked the first time
it's needed, and not after that. You can even store things in the state for
later use.
The singleton implementation object suggested by #jamesdlin. It basically does the
same thing, then puts the methods on the object instead of being static.
Another variant is to do exactly that, but with a private instance, and have the
public top-level functions forward to the singleton object. Then you get the
procedural API and still ensures that the state object is initialized.
(This may be better for testing, allowing you to have multiple state objects alive
at the same time).
Require people to call init.
If you can figure out how to rename this question, I'm open for suggestions.
In the Dart language, one can write a class with final fields. These are fields that can only be set before the constructor body runs. That can be on declaration (usually for static constants inside a class), in an initialiser list syntax when declaring the constructor or using the this.field shorthand:
class NumBox{
final num value;
NumBox(this.value);
}
Let's say I actually needed to do some processing on instance creation and can't just initialise the field before the constructor. I can switch to using a private non-final field with a getter:
class NumBox{
num _value;
NumBox(num v) {
_value = someComplexOperation(v);
}
num get value => _value;
}
Or I can get a similar behavior using a factory constructor:
class NumBox{
final num value;
factory NumBox(num v) {
return new NumBox._internal(someComplexOperation(v));
};
NumBox._internal(this.value);
}
I hit a similar bump when I tried learning Dart a few years back and now that I have more baggage, I still don't know. What's the smarter way to do this?
A factory constructor is a good way, it allows to pre-calculate without limitations any values that you then pass to a normal constructor to forward to final fields.
An alternative way is initializer list which is executed before the constructor body and therefore allows to initializer final fields:
class NumBox{
final num value;
NumBox(num v) : value = someComplexOperation(v)
}
In the initializer list you are not allowed to read this because the instance isn't fully initialized yet.
DartPad example
You should design your API with your user in mind, then implement it in whatever way is simpler and more maintainable to you. This question is about the latter part.
Making fields final is great when it's possible, and when it isn't, making them private with a public getter is a good alternative. It's your choice what to do, because it's you who is going to maintain your class, nobody else should need to look behind the public API.
If you need a complex computation, Günther Zöchbauer's suggestion is the first to turn to: Use a helper function. In some cases, you can even do it inline
class MyThing {
final x;
MyThing(args) : x = (() { complex code on args; return result;} ());
}
It gets ugly quickly, though, so having it as a static helper function is usually better.
If your complex computation doesn't match this, which ususally means that there is more than one field being initialized with related values, then you need a place to store an intermediate value and use it more than once when initializing the object.
A factory constructor is the easy approach, you can compute everything you need and then call the private generative constructore at the end. The only "problem" is that by not exposing a generative constructor, you prevent other people from extending your class. I quoted "problem" because that's not necessarily a bad thing - allowing people to extend the class is a contract which puts restrictions on what you can do with the class.
I tend to favor public factory constructors with private generative constructors even when it's not needed for any practical reason, just to disable class extension.
class MyClass {
const factory MyClass(args) = MyClass._; // Can be const, if you want it.
const MyClass._(args) : ... init .. args ...;
}
If you need a generative constructor, you can use a forwarding generative constructor to introduce an intermediate variable with the computed value:
class MyClass {
final This x;
final That y;
MyClass(args) : this._(args, _complexComputation(args));
MyClass._(args, extra) : x = extra.theThis, y = extra.theThat, ...;
}
All in all, there is no strict rule. If you prefer final fields, you can do extra work to make them final, or you can just hide the mutability behind a getter - it's an implementation and maintainability choice, and you're the one maintaining the code.
As long as you keep the abstraction clean, and keeps track of what you have promised users (generative constructor? const constructor?) so you won't break that, you can change the implementation at any time.
So I have seen code as such:
class Whatever {
final String name;
const Whatever(this.name);
}
What does change by the fact that the constructor is marked with const? Does it have any effect at all?
I have read this:
Use const for variables that you want to be compile-time constants. If
the const variable is at the class level, mark it static const.
(Instance variables can’t be const.)
but it does not seem to make sense for the class constructor.
The constructor can't have a constructor body.
All members have to be final and must be initialized at declaration or by the constructor arguments or initializer list.
You can use an instance of this class where only constants are allowed (annotation, default values for optional arguments, ...)
You can create constant fields like static const someName = const Whatever();
If the class doesn't have a const constructor it can't be used to initialize constant fields. I think it makes sense to specify this at the constructor. You can still create instances at runtime with new Whatever() or add a factory constructor.
See also
Dartlang const constructor - how is it different to "regular" constructor
Dart factory constructor - how is it different to “const” constructor
How to make a factory constructor that returns as const value
Why does Dart have compile time constants?
How to write abstract class constructors so that it will be flexible for extending in sub classes
The "old style" (still valid) enum is a good example how to use const
https://stackoverflow.com/a/15854550/217408
I am trying to initialize some event stream in a class. I want that stream to be final, but controlled by StreamController. I have tried following code:
import "dart:async";
class Dog {
final StreamController _onBarkController;
final Stream onBark;
Dog() :
_onBarkController = new StreamController(),
onBark = _onBarkController.stream;
}
But this code is illegal, because the access (even implicit) to this is forbidden in the initializer list.
Is there any way how to achieve this?
There isn't a great way to solve the general problem of needing to destructure some object into multiple final fields, which is basically what you're attempting here. But the good news is that usually you don't really need to. The two approaches I would recommend are factory constructors and not keeping derived state.
Factory constructors are great because you can perform arbitrary computation to create your arguments before calling the real constructor, which can usually only have an initializer list. In this case you can have a factory constructor create the StreamController and pass it and the stream to a private constructor.
Even better for you though, would be to not store the Stream in a field because you can get to it via the controller. I do this all the time with streams:
class Dog {
final StreamController _onBarkController = new StreamController();
Stream get onBark => _onBarkController.stream;
}
onBark is really a value derived from _onBarkController, so there's no need to store it.