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.
Related
Minimal reproducible code:
class Foo {
Foo();
factory Foo.named() => Foo();
}
class Bar extends Foo {
Bar() : super.named(); // Error
}
As there's no async-await thing in the factory constructor, and it instantly invokes the concrete constructor, so why isn't it allowed to use factory constructor like that?
Before null safety, null could be returned from a factory constructor but it is no longer a case. So, I think a factory constructor should now be allowed.
factory function can return subclass, which means can call subclass's init function.
if subclass self can call super.factory function, then it become cycling.
Calling a generative constructor creates a new object, then runs the constructor and super-class constructors to initialize that new object.
They are initializers which initialize the object created by the (now often implicit) new operator.
The super-constructor chained by the (non-redirecting) generative constructor is called to initialize the same object, and ensure that its fields are fully initialized, before ever giving anyone access to that object.
Calling a factory constructor does not create any new object, it just executed the body of that constructor which can do anything that normal code can. (That may or may not include calling a generative constructor to create an object. It can also just throw and never create any object.) A factory constructor cannot access this, because there is no "current object" before it returns one.
Let's assume that Foo has an int foo = 42; field. A factory constructor like the Foo.named here creates a new object by calling Foo() - the generative constructor.
When you do new Bar(), you create a new Bar object and ask the super-constructors to initialize that object. The named factory constructor has no access to that new object that would be created by calling new Bar(), it cannot access this and it cannot help initialize the foo field of that object. It creates a new, unrelated, Foo object and now you have 1) a partially initialized Bar object and 2) a Foo object, neither of which can be the result of calling a Bar constructor.
Your generative constructors must call a super-class generative constructor, which does the same until reaching the Object constructor. That's the only way to ensure that the newly generated object is fully initialized.
One of the main purposes of a factory constructor is to allow returning an existing instance. That's basically incompatible with a derived class constructor that must create a new object. (I suppose it doesn't necessarily have to be; you could imagine a design where two derived instances virtually inherit from a shared instance of a base class. However, that would be a lot of extra work for something of little benefit and that could be very confusing.)
Additionally, one of the other main purposes of a factory constructor is precisely to prevent a class from being subclassed by making all non-factory constructors private.
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;
}
Why does this code:
class _SequentialTextPageState {
String jsonTextPref = 'seqtext';
int jsonTextSuff = 10;
String jsonText = jsonTextPref + jsonTextSuff.toString();
}
generate these errors?
Error: The instance member 'jsonTextPref' can't be accessed in an initializer.
Error: The instance member 'jsonTextSuff' can't be accessed in an initializer.
It seems to me that concatenation between String and int is correct?
Dart initializes objects in multiple phases. Initializing members directly ("field initializers") occurs early in object initialization, before this becomes valid, so that phase cannot initialize members that depend on other parts of the object.
Dart provides multiple ways to initialize members, so if one member needs to depend on another, you can initialize it in a later phase by using a different mechanism. For example, you could do one of:
Add the late keyword to make the dependent member lazily initialized.
Move initialization of the dependent member into the constructor body.
In the case of a Flutter State subtype, you could initialize the dependent member in its initState method, which in some cases is more appropriate.
Note that in some cases you additionally can consider replacing the member variable with a read-only getter instead. For example, in your case, perhaps you could use:
String get jsonText => jsonTextPref + jsonTextSuff.toString();
That would be appropriate if jsonText should always depend on jsonTextPref and jsonTextSuff, would never need to have an independent value, and if it's acceptable for jsonText to return a new object every time it's accessed.
Dart does not allow field initializers to refer to the object itself. Fields must always be fully initialized before any access is given to the object begin created.
The initializers can only access static and top-level variables, not any instance variables on the object itself.
With null safety, you will be allowed to write late String jsonText = this.something + this.other;. That field will then not be initialized until it's first read or written, which is necessarily after the object itself has been created.
You can only use constant expressions as initializers. x=this.y is not constant.
The error was displayed when I did following:
class MyClass {
String id;
String[] imagePaths;
}
It will mark the String in the line String id; as error, but the error is in the next line, it should be List<String> imagePaths; instead of String[] imagePaths; then the error in the line above also disappears. This can be very confusing if you have a big class and the actual error is many lines underneath the first marked line (talking from experience...)
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.
When a class that contains code is instantiated, is the code is the class shared automatically by other instantiations of that same class? Eg. The data in the class that is instantiated may be minimal; however the code could be very significant. If the code is not "automatically" shared, is there a way to achieve that other than separating the code from the class data?
Sure.
Classes have the state and the behavior.
The state is encoded in member variables of the class. Each instance has its own copy of variables, thus its own state.
The behavior is specified by the methods implemented in the class ('methods' here stand for all static, non-static methods, setters and getters). Implementation is shared by all instances of the class, so all instances behave the same, but actual results and side-effects depend on instance state, obviously.