Asif Shaikh
Asif Shaikh

Reputation: 13

Role of private & non-private initializers in (Dart) private & non-private class constructors?

I'm new to OOP currently with intermediate level of understanding. I'm constantly gaining ground by learning Dart and C#. I'm also exploring the design patterns to really understand how it all clicks together based on different scenarios. As for now I'm trying to make sense of following 4 scenarios related to class constructors. I understand the implications of underscore at constructor level and at initializer level. But I am looking for something that may seem quite obvious and clear to experienced programmers out there. Please share your valuable insights as I don't know what I'm missing here.

Scenario 1: Private Constructor with no initializer

I know this is different from Singleton. Singleton allows single instantiation, this below does not even once. Is there something more to it?

Real World Example:

class Firebase {
  // Ensures end-users cannot initialize the class.
  Firebase._();
...
}

Scenario 2: Private Constructor with optional public or non-private initializer

What's the use of this type of private constructor that has non-private initializer (this.app)? Why have a non-private initializer (this.app) in a private constructor? What is achieved through this?

Real World Example:

class FirebaseAuth extends FirebasePluginPlatform {
/// The [FirebaseApp] for this current Auth instance.
  FirebaseApp app;

  FirebaseAuth._({required this.app})
      : super(app.name, 'plugins.flutter.io/firebase_auth');

  /// Returns an instance using the default [FirebaseApp].
  static FirebaseAuth get instance {
    FirebaseApp defaultAppInstance = Firebase.app();

    return FirebaseAuth.instanceFor(app: defaultAppInstance);
  }
...
}

Scenario 3: public Constructor with private initializer

Why have a private property in a non-private constructor? What is achieved through this?

Fictitious Example:

class Constructify {
  Map<String,dynamic> _property;
  Constructify(this._property);
...
}

Scenario 4: Private Constructor with private initializer

Why have a private initializer at all when the constructor itself is private? What is achieved through this?

Real World Example:

class FirebaseApp {
  /// A [FirebaseApp] instance can only be accessed from a call to `app()` [FirebaseCore].
  ///
  /// This constructor ensures that the delegate instance it is constructed with is one which extends [FirebaseAppPlatform].
  FirebaseApp._(this._delegate) {
    FirebaseAppPlatform.verifyExtends(_delegate);
  }

  final FirebaseAppPlatform _delegate;
...
}

Upvotes: 1

Views: 483

Answers (1)

julemand101
julemand101

Reputation: 31219

Scenario 1: _ in Dart means the variable/method/function/constructor is package private. So as long as we are inside the same package, we are allowed to use the field. So in Scenario 1 this actually means we can only create Firebase objects if we call the constructor from the package where Firebase has been declared. This will also prevent you from extending the class in another package since we cannot call the constructor on the Firebase class we are extending from.

Scenario 2: The package private constructor ensures that objects can only be created by code from the same package. The named app parameter is marked required so it is not optional. After the object has been created, you can in this case change the app variable. I don't know if this makes sense in this scenario but you can do it. I would properly in most cases mark app as final.

Scenario 3: The private field can be set to a value using the constructor but since the field is package private, we can ensure nobody outside our package can access the field afterwards.

Scenario 4: A package private constructor is used by some other code in the same package. If you want to ensure only your own package are allowed to create new objects of FirebaseApp and don't want code outside your package to get access to the field _delegate, you can do what this example does.

Upvotes: 1

Related Questions