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.
Related
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.
Even though I am familiar with singleton, Dart's factory is confusing. I have seen an existing question, but the only thing I got from the answer is that the name can be whatever identifier that starts with an _. Even though the person had asked why it should be called, the answer does not seem to be explaining that.
If I comment out the Dog._internal(); line, I get Method not found: 'Dog._internal'. It looks like calling a method, but is it like C's function prototype? But it has no return type. Can someone explain the Dog._internal(); line to me?
class Dog
{
static final Dog dog = Dog._internal();
//Dog._internal();
factory Dog()
{
return dog;
}
}
There are multiple concepts going on so lets go through the example:
factory Dog()
{
return dog;
}
This defines a factory constructor. Factory constructors are much like normal static methods but must always return an object which are compatible with the type of which the factory constructor is part of. In our example the factory constructor must return a Dog object.
It is not a constructor in that sense that we already have created a object when we enter this method. Again, it can be compared to static Dog Dog() but is allowed to override the default constructor. So we must create the object manually and return it.
This allows us to control the behavior of when objects are created and in our case allows us to have a singleton pattern so when somebody are trying to create an instance of Dog they will always get the same object.
Dog._internal();
This is called a named constructor. Constructors in Dart can have given names which makes it easier to distinguish different constructors. But also because Dart does not allows us to override methods with different number of parameters.
Also, because of the name starting with _ it means this constructor is marked private and cannot be used outside of the library it is part of. So if your code is part of a library, the code importing your library are not allowed to call your private constructor.
This is again a nifty trick to allow us to make a singleton since we don't want other than our own code to create a new instance (which are the only instance we want to create).
static final Dog dog = Dog._internal();
This is essential creating the singleton. The reason for this is that static variables in Dart are lazy-evaluated so the value dog does not really have any value before it is called. After first call, the value are "cached" so Dog._internal(7) are only called once as long our application (or more specific, our isoleate instance) are running.
I would properly call the variable _instance or _dog so it is also private.
Dog.foo(); defines a named constructor named foo that takes no arguments and has no body. It's equivalent to Dog.foo() {}. Similarly, Dog._internal(); defines a named constructor named _internal. This would be more obvious if the constructor took arguments and did work, for example:
class Dog {
static final Dog dog = Dog._internal(7);
Dog._internal(this.years) {
registerAnimal(this);
}
factory Dog() {
return dog;
}
int years;
}
I'm trying understand what's the mean of this two final lines of code, on colons... It's a syntax question.
I'm following this github example and I have this doubt on my head.
Can someone help me with this?.
class DietPlan extends ParseObject implements ParseCloneable {
DietPlan() : super(keyDietPlan);
DietPlan.clone() : this();
The part after : is called "initializer list.
It is a list of expressions that can access constructor parameters and can assign to instance fields, even final instance fields.
The first colon, i.e. DietPlan() : super(keyDietPlan); means that you are calling the super constructor, constructor of ParseCloneable in this case.
This is a core OOP concept, you can extend or implement one class to another and you must call the superclass constructor if you do so. This is just a style of doing the same in Dart.
The second colon works in similar way, to understand that you need to understand what is cloning of objects,
Object cloning refers to creation of exact copy of an object. It creates a new instance of the class of current object and initializes all its fields with exactly the contents of the corresponding fields of this object.
This is whats happening on the second line.
I just started BlackBerry development and I follow some of the tutorials to become familiar with the UI objects and so on and I saw/tried this:
private MenuItem menuItemClose = new MenuItem(new StringProvider("Contacts"), 0, 0) {
public void run() {
onClose();
}
};
I have not seen this way of instantiating an object before (thinking about new MenuItem), could someone explain what is happening?
And what is the difference between instantiating objects inside method definitions and in "instance variable section" like this?
That's called an "anonymous inner class."
Anonymous inner classes are classes which are created within another class but not named. They are instantiated by their interface or abstract base class definition and given their missing implementation inline with the instantiation.
In this case, MenuItem is abstract - it's missing its run() method. You're providing the implementation of its run() method here on lines 2-4.
Take a look at this JavaWorld article for more information about the various types and uses of inner classes.
As for the second part of your question "what is the difference between instantiating objects inside method definitions and in "instance variable section" like this?" -- the difference is scope, and when the object is instantiated.
Non-static member variables with initial values are created when the object which contains them is instantiated. The initial value assignment (initialization) executes at that time as well.
Static member variables with initial values are created and initialized when the class is loaded by the VM's class loader. With eager ClassLoading, this will occur at the start of the application. With lazy ClassLoading, this will occur the first time the class is referenced by the application. I believe by default most classes that aren't part of the Java runtime are loaded lazily.
Both static and non-static member variables have object-level scope and are accessible by other objects according to their access modifier (public/private/protected).
Non-static member variables are part of an object instance, and as such they are marked for garbage collection when that instance is orphaned or goes out of scope. Static member variables are only garbage collected if the class that contains them is unloaded. This only occurs if the ClassLoader instance which loaded said class is garbage collected. See this question for more info about that.
Local variables (variables which are defined within a method) with initial values are created and initialized when that line is executed as part of normal method execution. They are marked for garbage collection (destroyed) once they go out of scope (after the method in which they're contained finishes executing).
This creates an anonymous inner class which extends MenuItem and overrides the run method. It is standard Java and has nothing to do with Blackberry.
When you define a new inner class inside the method call, it's known as an 'anonymous inner class'. Anonymous inner classes are useful when you don't really need a reference to the object after the initial method call.
final Object obj = new Object(); // Standard instantiation
System.out.println(obj); // Prints java.lang.Object#5c005c
// Anonymous inner class
System.out.println(new Object() { }); // Prints Foo$1#2500250
// Anonymous inner classes work with interfaces too
new Thread(new Runnable() {
#Override
public void run() {
// Runnable is an interface
}
}).start();
This is quite a common pattern and can be useful to define 'one-time-use' objects, perhaps at the expense of readability.
I have a question regarding dependency injection.
say i want to create a class
call it, WebGetTask
WebGetTask would need a dependency to HttpService
bad code 1
Code:
private HttpService httpService;
...
List<WebGetTask> list = new ArrayList<WebGetTask>();
for(...)
{
list.add(new WebGetTask(httpService));
}
...
ok. i know this is bad, because httpService is injected, but its never used, except for the creation on a new WebGetTask
ok
bad code 2
Code:
private WebGetTaskFactory webGetTaskFactory;
...
List<WebGetTask> list = new ArrayList<WebGetTask>();
for(...)
{
list.add(webGetTaskFactory.newTask());
}
...
i think this is better, because we use a factory
but...
but..
from where i'm standing,
i can see that
in WebGetTaskFactory
we are still injecting a HttpService and not doing anything to it except for the sole purpose of creating a new WebGetTask
so
to recap
my question is
how do i design a factory class (WebGetTaskFactory), that creates new objects (WebGetTask) when the new objects require a dependency (HttpService) on their constructor without simply injecting and passing the dependency (HttpService) ?
or rather, is this the way to do it? if so, then it's all good, if its not, then please guide me to how to properly use DI and factory pattern.
thanks.
I'm going to assume that the code you have shown is part of a DownloadManager class, and that you inject your dependencies via the constructor. In this case, I would expect the start-up code which glues everything together to look like this:
IHttpService httpService = new HttpService();
IWebGetTaskFactory webGetTaskFactory = new WebGetTaskFactory(httpService);
IDownloadManager downloadManager = new DownloadManager(webGetTaskFactory);
The DownloadManager class only knows about the IWebGetTaskFactory interface. It does not know about IHttpService, thus satisfying the law of Demeter.
edit: After re-reading your question, it seems that you are worried that you are not "using" the HttpService in your factory, except to pass it on to a new WebGetTask. This is OK. Both WebGetTaskFactory and WebGetTask need an HttpService instance to do their job. This is not a violation of the law of Demeter.
Okay, there's nothing specifically wrong under the LoD about passing an implementation object, a "plugin" in the constructor. What's important is that the interface of the class doesn't tell you much about that implementation.
If your interface to WebGetTask depends on the exact implementation of HttpService, that violates the Law of Demeter.
The trick here is to think about the interface signature of WebGetTask. The name itself suggests that you're not quite following the Law of Demeter — or principle of least knowledge — because you're defining a class that (1) is defined as being specific for the web, and (2) is a verb instead of a noun.
Now, neither of those is necessarily wrong, but they are both "OO smells" if you will, signs that you may not be thinking object-ly enough.
So let's try "refactoring" the design. First thing, think about a GetTask that has no "web" associated with it. You can then, either at construction time or at some later time build a service object and pass it in. If it's HttpService, that's fine, but the user of your class doesn't need any information about what's under the covers.
Second thing, let's make it a noun. Call it TaskFactory — your intuition was leading you right there — with a ctor that takes an IOService, which I've just invented as being the abstract interface implemented by HttpService.
Now, you have (this is sort of Java/C++ pseudocode, don't get excited about syntax details):
class Task { ... }
class TaskFactory {
public TaskFactory(IOServer svc){...}
public Task get(){...}
}
and you use it by writing
TaskFactory fac = new TaskFactory(new HttpService());
Task tsk = fac.get();
Now, we kow the minimum about the innards of TaskFactory, the IO service, and for that matter Tasks.
There are two ways of DI: the first one is a constructor one, which is usefull when only one or two objects are injected, and a setter one (actually as many setters as needed).
If you want to use a factory method for DI than in principle its same as a constructor based one.
Example 1, for a constructor DI:
list.add( new WebGetTask( httpService ) ) ;
Example 2, for a setter DI:
WebGetTask webGetTask = new WebGetTask();
webGetTask.setHttpService(httpService);
// set other dependencies
list.add(webGetTask);
The factory method is best for when you need to use some greater logic when creating objects that may behave differently, but have the same interface, thus the LoD. Lets assume there is a DownloadManager interface implemented dynamically based on the factory parameter(s).
Example 3, creation logic encapsulated into a factory method:
public static DownloadManager createDownloadManager(HttpService httpService){
if(null!=httpService){
WebGetTask webGetTask = new WebGetTask();
webGetTask.setHttpService(httpService);
// set other dependencies
return new DownloadManagerImpl1(webGetTask);
} else {
return new DownloadManagerImpl2();
} // if-else
}