I've found the same question here, but I cannot comment it. So I started this thread.
I want to make an abstract database class, which is implemented by a real database classes like postgresdb class. And I want to make private fields and abstract methods in an abstract db class to remain private in childs. Cause there is no any sense in making password and other stuff public.
I can make it in one file, but is there any ways to make it in different files? Cause classes are quite big. One of the commentators advised to use library keyword. But in doesn't work, at least in Intellij IDEA. Is it a bug or am I doing something wrong?
For example it's a base class:
abstract class DBSQL {
final _initDBFilePath = '.';
final String _address;
final int _port;
final String _dbname;
final String _username;
final String _password;
}
This is a child class:
class DBPostgres implements DBSQL {
#override
final String _id;
#override
final String _initDBFilePath = 'path-to-sql.sql';
#override
final String _address;
#override
final int _port;
#override
final String _dbname;
#override
final String _username;
#override
final String _password;
DBPostgres(
{#required address,
#required port,
#required dbname,
#required username,
#required password})
: _address = address,
_port = port,
_dbname = dbname,
_username = username,
_password = password,
_id = '$address:$port/$dbname';
}
IDEA wants me to remove overrides. I tryied to use #visibleForOverride from meta package, but doesn't work too.
I use Dart 2.12.0-224.0.dev with meta-1.3.0 on Win10 x64.
I know that in Java there is no such a problem. You can override everything in the ancestor class.
If your classes are in different libraries, then you cannot override private members.
The member are private, which means that you can't see them at all from a different library, and therefore you also can't override them.
You're trying to declare other fields with the same names, but the way library privacy in Dart works, that's actually going to be different names because library private names are unique to the library they are in. So, your variables have different names than the original, and code trying to access the original's variables won't see yours.
You have to be in the same library for this to work. Then there should be no problem.
Related
I have this method
void doSomething<T>() { ... }
and a variable of type T
T someVar = ...;
how can I use doSomething method to perform an action on someVar, something like this?
doSomething<someVar.Type>();
in fact, I want to access Type T form variable.
here is the example
class BlocManagerProvider extends StatefulWidget {
const BlocManagerProvider({
#required this.child,
#required this.blocs,
Key key,
}) : super(key: key);
final Widget child;
final List<Cubit<Object>> blocs;
#override
_BlocManagerProviderState createState() => _BlocManagerProviderState();
}
class _BlocManagerProviderState extends State<BlocManagerProvider> {
#override
Widget build(BuildContext context) => widget.child;
#override
void dispose() {
for (final Cubit<Object> bloc in widget.blocs) {
BlocManager.instance.dispose<type>();
}
super.dispose();
}
}
Future<void> dispose<T extends Cubit<Object>>() async {
final String objectKey = _getKey<T>(key);
if (_repository.containsKey(objectKey)) {
await _repository[objectKey].close();
_repository.remove(objectKey);
await removeListener<T>(key);
}
}
Dart does not provide a way to go from an object of type X to a type variable bound to X. There are good technical reasons for not allowing that (it allows the web compilers to know at compile-time which types can ever be bound to a type variable, which allows it to reduce the compiled code).
The dispose method is treating the type argument as its only argument and acting on the value of that type argument.
It makes me think you're trying to do something that the language is not designed for.
You're passing in a type argument, and then the code inspects that type of argument and behaves differently depending on the value. That's not what's usually meant by being "generic" - to act the in the same (generic) way independently of the types, so the only real effect of passing a type is to make the return type match the argument type.
(That's why Java can erase type arguments at run-time).
So, if you need to know a type for some object, either that object must provide it for you, or you have to store it from earlier (perhaps when the object was created).
So, if you really need to access the type argument that the cubit is implementing Cubit<X> of, the Cubit class needs to make it available to you. That will usually be with a method with a callback (like a visitor), something like:
abstract class Cubit<T> ... {
...
R visit<R>(R Function<C extends Cubit<T>, T>(C value) action);
}
class SomeCubit<T> extends Cubit<T> {
...
R visit<R>(R Function<C extends Cubit<T>, T>(C value) action) =>
action<SomeCubit<T>, T>(this);
}
If something like that's available, then you can do what you want as:
bloc.visit(<C extends Cubit<T>, T>(_) => BlocManager.instance.dispose<C>());
If something like that is not available, then you are in trouble.
You can detect a number of known types, with a bunch of if statements, but that's unlikely to be sufficient.
That means you need to remember the type from earlier, but since it looks like you just get a List<Cubit<Object>> that has already been created, that doesn't seem practical either.
If the BlocManager is your own class, consider changing it to use Type objects instead of type arguments (which is contrary to everything I usually say you should do), because then you can call ..dispose(bloc.runtimeType). I'd prefer to avoid that, but if other constraints make what you do impossible, then it might be the lesser evil.
TL;DR: Named parameters are optional as a result of a conscious design choice. Short of having official language support, is there any way to enforce (and inform) required named arguments?
I find it extremely useful to use named parameters when defining a class. Take, for instance, an Ability in an MMORPG:
class Ability {
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
effectDuration and recast both carry the same type of information (i.e. duration of time) and are likely represented by the same datatype. It is easy to mix up which number goes where. However, they are both information vital to the correctness of the object, so they can't be missing during instantiation.
I could just break the program via a try-catch to enforce the requirement of those parameters, but that doesn't sound like fun for someone who uses the class and has no idea (short of reading the docs and understanding intuitively what the class does) that they are required.
Is there any way to enforce the requirement of certain named parameters while managing to inform the caller of said requirement and/or help them use it correctly?
The meta package provides a #required annotation that is supported by the DartAnalyzer.
Flutter uses this a lot and provides #required directly from import 'package:flutter/foundation.dart'
foo({#required String name}) {...}
foo(); // results in static warning
#required doesn't check if the passed value is null or not, only that a value was actually passed on the call site.
To check for null you can also use assert() to check for passed values
class Ability {
Ability(this.name, this.effectDuration, this.recast) : assert(name != null), assert(effectDuration != null), assert(recast != null);
final name;
final effectDuration;
final recast; // wait time until next use
// ...
}
[Update] New as-of Dart 2.0
In dart 2.0 the required keyword has been added to the language as part of the null-safety update. This means that you get a compiler-enforced non-null value rather than one checked by the analyzer; this makes the null check completely redundant.
This means that this code does effectively the same as the old code below, except that you never have to worry about the assertion throwing as the values for name, effectDuration, and recast cannot be null.
class Ability {
final String name;
final Duration effectDuration;
final bool recast;
final String? description;
Ability({
required this.name,
this.effectDuration = Duration(seconds: 1),
this.recast = false,
this.description,
});
}
Before Dart 2.0
Yes, there is!
Here's an example:
class Ability {
final String name;
final Duration effectDuration;
final bool recast;
final String description;
Ability({
#required this.name,
this.effectDuration = new Duration(seconds: 1),
this.recast = false,
this.description,
}):
assert(name != null),
assert(effectDuration != null);
}
You don't have to assert that name is not equal to null, but it might be useful for you.
Although you could use the flutter foundation package as described in the accepted answer, when I am working with model classes that don't need to know about Flutter, I prefer to use the meta package directly. That way it doesn't create an unnecessary dependency on the framework. This allows you to share the Dart code even outside of Flutter.
Add meta to pubspec.yaml:
dependencies:
meta: ^1.1.7
Import it in your class file:
import 'package:meta/meta.dart';
Use the #required annotation in your code:
class Person {
String name;
int age;
Person({#required this.name, this.age,});
}
So name is a required parameter, but age isn't.
final person = Person(name: 'Bob');
Update:
In an upcoming version of Dart, the required keyword should be added by default, so no imports will be necessary at all.
As of 2.12 with null safety you can use required keyword (not #required). Also no need to import any additional packages.
In this example named parameter name is optional while effectDuration and recast are required.
class Ability {
final name;
final effectDuration;
final recast;
Ability({this.name, required this.effectDuration, required this.recast});
}
Update pubspec.yaml, for example:
environment:
sdk: ">=2.12.0-0 <3.0.0"
References:
Sound null safety
How does #required compare to the new required keyword?
With null safety:
Non-nullable named parameter:
You need to either mark the named parameter required or provide a default value or even mark it late. For example:
class Foo {
final int a;
final int b;
late final int c; // Mark late and provide value later.
Foo({
required this.a, // Mark required.
this.b = 0, // Provided a default value.
});
}
Nullable named parameter:
You don't need anything special to handle them.
class Foo {
final int? z;
Foo({
this.z,
});
}
If you want declare to a empty variable but that has methods inside , you can:
1)Use the late keyword
2)Declare the type like possible null returned example: int? number;
3)Initialize the variable empty, for example :
List listOfNumbers = [];
Map mapOfPerson1 = {};
And so you can use the methods of the variable to add them values
'm trying to create a reusable link class that extends Link. I have a webpage with about 7 menu items and I'm using inheritance for my application. I want to create a reusable link class to shorten the length of my code..
As of now the link creates and runs fine when I add(new Link....) as an anonymous class inside oninitialize().
The custom link class (which is an inner class of the base page) works fine when I hard code the instance of the new page to go to, and assign it to a "Page" reference, then pass it into setResponsePage();
The problem is, I'm passing trying to be able to pass object through the constructor generically. When I pass it through the constructor, and try to travel to the new page, I get a session has expired.
I've tried using generics for the class, and I've also tried just declaring a Page reference as a parameter value. Am I supposed to use some sort of Model? Or can someone provide an example of how to do this? I want to be able to use this custom link class to add new links for the 7 menu items, which each have there own class...
Code that works:
add(new Link("userPageLink")
{
public void onClick()
{
pageTitle = "User";
Page next = new UserPage();
setResponsePage(next);
}
});
Modified code that gives page expired upon click:
public class CustomLinkToNewPage extends Link
{
private String title;
private Page next;
public CustomLinkToNewPage(String id, String title, Page newPage)
{
super(id);
next = newPage;
this.title = title;
}
#Override
public void onClick()
{
SSAPage.pageTitle = title;
setResponsePage(next);
}
}
This might be due to the fact that in the first version you crate the Page object when the onClick method of the Link object is called and in the second version, the Page object is created on Page-construction (way earlier).
You might get the result if you pass the Pageclass of the responsepage instead on an instance.
Component features setters for these either with
public final <C extends IRequestablePage> void setResponsePage(java.lang.Class<C> cls, PageParameters parameters)
or without parameters.
public final <C extends IRequestablePage> void setResponsePage(java.lang.Class<C> cls)
See Javadoc for more information.
I ended up doing:
public class CustomLinkToNewPage<T extends SSAPage> extends Link
SSAPage is my base page that extends WebPage... So any object passed in to this class's constructor must extend SSAPage as well.
public CustomLinkToNewPage(String id, Class<T> name)
Then I passed in the .class reference to the object, and created a new instance of the object using reflection.. then set that instance to Page, and passed it to setResponsePage in my onClick. Worked nicely, as I couldn't figure out how to do Nicktar's way. So this an alternative in case anyone else runs into this issue.
I have a BlackBerry application that starts (App load) with a Registration screen when the App is first installed. Later, the App will load with the home screen. Registration screen only appears on first load. I am achieving this by storing a boolean value in PersistentStore. If the value exists, then Registration screen will not appear.
PersistentStoreHelper.persistentHashtable.put("flagged",Boolean.TRUE);
PersistentStoreHelper.persistentObject.commit();
UiApplication.getUiApplication().pushScreen(new MyScreen());
I am aware of the fact that in order to delete the Persistent Store on deleting/uninstalling the App, I have to make the Hashtable a subclass of my own and therefore I have declared the Hashtable in a separate class:
public class PersistentStoreHelper extends Hashtable implements Persistable{
public static PersistentObject persistentObject;
public static final long KEY = 0x9df9f961bc6d6daL;
public static Hashtable persistentHashtable;
}
However this has not helped and the boolean value of flag is not cleared from PersistentStore. Please advice.
EDIT: When I change the above PersistentStoreHelper class to
public static PersistentObject persistentObject =
PersistentStore.getPersistentObject(KEY);
and remove
PersistentStoreHelper.persistentObject =
PersistentStore.getPersistentObject(PersistentStoreHelper.KEY);
from class B where boolean value is being saved, I observe that the boolean value is removed every time the App is closed. This should not happen and the value should only be removed in case the App is deleted/uninstalled. Any pointers?
The way this works is that the BlackBerry OS looks at the objects you are storing in the PersistentStore. If it recognizes that those objects can only be used by your app, then it will delete them when you uninstall the app. However, if the classes of the stored objects are classes that are used by other apps, then your data will not be deleted.
You have declared your helper class like this:
public class PersistentStoreHelper extends Hashtable implements Persistable{
but the helper class is not what is being stored. Your helper class is just a helper, that stores other things for you. In your case, it is storing this:
public static Hashtable persistentHashtable;
but, that object is of type java.util.Hashtable, which is a class used by many apps. So, it won't be deleted when you uninstall your app. What you should do is something like this:
public class PersistentStoreHelper implements Persistable { // so inner class = Persistable
public static PersistentObject persistentObject;
public static final long KEY = 0x9df9f961bc6d6daL;
/**
* persistentHashtable is now an instance of a class that
* only exists in your app
*/
public static MyAppsHashtable persistentHashtable;
private class MyAppsHashtable extends Hashtable implements Persistable {
// don't need anything else ... the declaration does it all!
}
}
I can't see it here, but I'm assuming that somewhere you have this code:
persistentObject = PersistentStore.getPersistentObject(KEY);
and then when you want to save the data back to the store, you're doing something like this;
persistentHashtable.put("SomeKey", someNewData);
persistentObject.setContents(persistentHashtable);
persistentObject.commit();
just adding data to the persistentHashtable doesn't save it (permanently). Hopefully, you already had that part somewhere.
Note: if you make these changes, don't expect this line of code to work, the next time you run your app:
persistentHashtable = (MyAppsHashtable)persistentObject.getContents();
because the last version of your code did not use the MyAppsHashtable class, so the loaded data won't be of that type. This is one reason that it's important to get this right the first time. In general, I always wind up saving data in the PersistentStore that's contained in one top level Hashtable subclass, that implements Persistable. I may later change what goes in it, but I won't ever change the signature of that top-level storage object. Hopefully, you haven't released your app already.
Update: In response to your comment/question below:
if (PersistentStoreHelper.persistentObject.getContents() == null) {
PersistentStoreHelper.persistentHashtable = new MyAppsHashtable();
PersistentStoreHelper.persistentObject.setContents(PersistentStoreHelper.persist‌entHashtable);
} else {
PersistentStoreHelper.persistentHashtable =
(MyAppsHashtable)PersistentStoreHelper.persistentObject.getContents();
}
I'm refactoring a Blackberry application and I have a scenario where I think I'm currently using a global variable, but I'm not sure if that's the right thing to do. Briefly, my scenario is the following -
My app first requires the user to login. The (uid, pass) are sent to a web service which determines if the login is valid and returns some additional data. I have a model object on my application that looks something like this - (After a succesfully calling login)
class UserDataModel
{
private String username;
private String password;
private String fullName;
private String age;
...
/* Getters and Setters */
}
I also have a UserPreferencesModel which contains all the preferences that the user has saved. (I need to back them up to our database / restore them across devices etc.)
Additionally, in what context are Globals generally used in the context of mobile development?
Thanks,
Teja.
Well, I made a simple example how you can to use the RuntimeStore, I hope that this be of helpful
public class myData
{
long ID = 0xf46f5a7867d69ff0L;
String d1;
RuntimeStore runTS = RuntimeStore.getRuntimeStore();
public void setData(String _d1)
{
try
{
syncronized (runTS)
{
runTS.put(ID, _d1);
}
}catch(Exception ex){}
}
public String getData()
{
String s;
try
{
s = (String)(RuntimeStore.getRuntimeStore().get(ID));
}catch(Exception ex){}
return s;
}
}
There is nothing particularly special about BlackBerry in regards to using singletons. Of course, true constants should be just statics. And all of them should be final but Strings: there is a memory usage penalty if a static final String is reused often in your code.
What singleton gives you is the ability to replace or remove complex models with relatively long lifetime via a single point of control.
In your example, DataModel is a good candidate. BlackBerry is a personal device, so there is a big chance this DataModel with user profile and, probably, additional data, will survive for the lifetime of the active application.
So,
class UserDataModel
{
private static UserDataModel singleton;
public static void login() {
//get credentials
//authenticate
singleton = new UserDataModel(... user profile data...);
}
public static UserDataModel getInstance() { return singleton; }
private String username;
private String password;
private String fullName;
private String age;
...
/* Getters and Setters */
}
This way of doing it is a valid, a little simplified, example. If something changes (say, server host), all you need to do is to replace singleton. Also, it opens up a possibility to use polymorphism, if UserDataModel implementation is different for different servers, etc. There are many benefits to it at the cost of one extra variable in a chain of accessors. Again, there is nothing special about BlackBerry here, this reasoning is valid in any Java application.
Why the example is simplified is because you need to think about threads. If there is even a remote chance that something somewhere will access getInstance() on a different thread than login(), you have to properly synchronize them (even though I was never able to break a simple object reference by accessing/updating it from different threads on BlackBerry).
their are some scenarios when having static variable is good idea. like for Constant String fields.
here is the link to blackberry official Best practice document for writing efficient code for blackberry platform.
Black Berry: Best Practices: writing efficient code