While studying Dart, I noticed that private properties start with an underscore. So what do private properties mean?
class OfficialName extends Name {
// Private properties begin with an underscore
final String _title;
OfficialName(this._title, String first, String last)
: super (first, last);
#override
String toString(){
return 'S_title. ${super.toString()}';
}
}
Private properties are those properties that are only accessible in the file in which they were declared. In other words, only dart code in the dart file, where these private properties are found, "know" the private properties.
Consider the following example
In lib/foo.dart
class Foo {
var _foo = 'foo';
var bar = 'bar';
}
main() {
print(Foo()._foo); // foo
print(Foo().bar); // bar
}
Then in lib/bar.dart
import './foo.dart';
main() => {
// print(Foo()._foo); // this won't work
print(Foo().bar); // bar
}
Running both files will show the commented results. But if the print(Foo()._foo); line is uncommented in bar.dart, the compiler will throw an Error, that the getter '_foo' isn't defined for the class 'Foo'. This is because the _foo property on the Foo class is private to the foo.dart file.
In Dart, every file is a library. So it makes sense that privacy or private properties are scoped to each library.
To create a private property, be it a field or a method, simple prefix its name with an underscore _.
So when coding, if there are properties you feel that other dart files (or libraries) shouldn't access, (maybe because of isolating logic), then you can make them private (by prefixing with underscore _).
Dart privacy is indeed only on a per library basis.
I understand this way, let's talk about your example.
final String _title; means our title here is private.
If we declare a variable with underscore, we can't change its property.
Let's create an object of OfficialName and print it.
OfficialName ofName = OfficialName("Dr", "John", "kim");
print("From constructor=> title: ${ofName._title} first: ${ofName.first} last: ${ofName.last}");
Now if we like to change the attribute value of this object, we can do
ofName.first= "new value" however, we can't change _title here. I think private property as an immutable object.
Example code
class Name {
String first;
String last;
Name(this.first, this.last);
}
class OfficialName extends Name {
// Private properties begin with an underscore
final String _title;
OfficialName(this._title, String first, String last) : super(first, last);
#override
String toString() {
return 'S_title. ${super.toString()}';
}
}
// Main function
void main() {
OfficialName ofName = OfficialName("Dr", "John", "kim");
print(
"From constructor=> title: ${ofName._title} first: ${ofName.first} last: ${ofName.last}");
///let's change some property
/// this will show errors
ofName._title = "changed title";
ofName.first = "firstName";
ofName.last = "lastName";
print(
"After changed=> title: ${ofName._title} first: ${ofName.first} last: ${ofName.last}");
}
For clear information visit language-tour
The underscore determines the visibility of that identifier to the outside:
The import and library directives can help you create a modular and shareable code base. Libraries not only provide APIs, but are a unit of privacy: identifiers that start with an underscore (_) are visible only inside the library. Every Dart app is a library, even if it doesn’t use a library directive.
From the dart documentation
Related
I'm trying to figure out how to use Android's Room library for implementing a prepopulated sqlite database in my app and I came across this Android tutorial. One of the lines (the one in the title) confuses me though, because in another tutorial (also by Android), this line isn't present. Why is this line of code present in the first tutorial but not the second? What is its purpose?
I ask this because my code (which I'm basing off the second tutorial) doesn't include this line and yet this post by a different user attempting to do something similar with a prepopulated database does include it.
Here is some of the code I have (each of the fields has a getter method which just returns this.thatfield'sname):
#Entity (tableName = "words")
public class Words {
#PrimaryKey
#NonNull
#ColumnInfo (name = "word_id")
private int wordId;
#ColumnInfo(name = "a_words")
private String aWords;
#ColumnInfo(name = "b_words")
private String bWords;
#ColumnInfo(name = "c_words")
private String cWords;
This code gives me a "Cannot find setter for field" but just changing the fields from public to private seems to solve that (not sure if this is the best way to solve this error, though).
Why is this line of code present in the first tutorial but not the second?
That line is an additional class constructor that takes 1 non-null String and sets the mWord member/variable to the provided String.
Without then you can only use myWord = new Word(); to instantiate a Word object and the value would be either the default value if provided or null.
With the additional constructor then you could use both
myWord = new Word();
or
myOtherWord = new Word("A Word");
So, in short it's provided an alternative way of constructing/instantiating a new Object of that Class.
Using your code then you could have, for example :-
#Entity(tableName = "words")
class Words {
#ColumnInfo(name = "word_id")
#PrimaryKey
private int wordId;
#ColumnInfo(name = "a_words")
String aWords;
#ColumnInfo(name = "b_words")
String bWords;
#ColumnInfo(name = "c_words")
String cWords;
public void setWordId(int wordId, String aWord, String bWords, String c) {
this.wordId = wordId;
this.aWords = aWord;
this.bWords = bWords;
this.cWords = c;
}
}
Note for demonstration the parameter names use 3 different standards, ideally you would stick to a single standard/convention for naming the parameters.
So now you could use the one constructor that expects 4 parameters e.g.
myWord = new Words(1,"Apple","Banana","Cherry");
which equates to
myWord = new Words();
myWord.wordId = 1;
myWord.aWords = "Apple;
myWord.bWords = "Banana";
myWord.cWords = "Cherry";
As you have specified a constructor, the default constructor is no longer usable.
What is its purpose?
As can be seen, additional constructors, can reduce the amount of coding, there use will also prompt for the values (hence the use of useful parameter names improves i.e. c as above is not very meaningful at all (although in conjunction with the other parameters if would be better than x))
I m preparing a class in my flutterfire project and their I want to use some method Which can't change further so that I want to know consept of static keyword in Dart ?
"static" means a member is available on the class itself instead of on instances of the class. That's all it means, and it isn't used for anything else. static modifies members.
Static methods
Static methods (class methods) don’t operate on an instance, and thus don’t have access to this. They do, however, have access to static variables.
void main() {
print(Car.numberOfWheels); //here we use a static variable.
// print(Car.name); // this gives an error we can not access this property without creating an instance of Car class.
print(Car.startCar());//here we use a static method.
Car car = Car();
car.name = 'Honda';
print(car.name);
}
class Car{
static const numberOfWheels =4;
Car({this.name});
String name;
// Static method
static startCar(){
return 'Car is starting';
}
}
static keyword in dart used to declare a variable or method that belongs to just the class not the instants which means the class has only one copy of that variable or method and those static variables(class variables) or static methods(class methods) can not be used by the instances created by the class.
for example if we declare a class as
class Foo {
static String staticVariable = "Class variable";
final String instanceVariable = "Instance variable";
static void staticMethod(){
print('This is static method');
}
void instanceMethod(){
print('instance method');
}
}`
the thing here to remember is static variables are created only once and every instance crated by the class has different instance variables. therefore you can not call static variables form the class instances.
following codes are valid,
Foo.staticVariable;
Foo().instanceVariable;
Foo.staticMethod();
Foo().instanceMethod();
there for following codes will give errors
Foo().staticVariable;
Foo.instanceVariable;
Foo().staticMethod;
Foo.instanceMethod
Use of static variables and methods
you can use static variables when you have constant values or common values that are relevant for the class.
you can read more here - https://dart.dev/guides/language/language-tour#class-variables-and-methods
In TypeScript, I have been separating non-instance variables out of my classes and into a namespace with the same name as the class. For example:
class Person
{
age: number;
constructor(age: number)
{
this.age = age;
}
}
namespace Person
{
export let numberOfFingers: number = 10;
}
export default Person;
as opposed to this:
class Person
{
static numberOfFingers: number = 10;
age: number;
constructor(age: number)
{
this.age = age;
}
}
export default Person;
Is there any benefit to either of these methods?
As far as typechecking and code generation is concerned, both methods produce exactly the same results. I can offer two not very strong arguments in favor of static members:
it's the most obvious thing to do, it does not require knowledge of advanced parts of the language (declaration merging) to understand the code
if you ever need to have a function that creates and returns class definition (as described for example here, to simulate static generic member or to add a mixin), then namespaces will not work - you can't have namespace inside a function.
I'd like to write my own macro for creating property like objects in Haxe.
This question is not so much about properties but more about writing macros.
(probably NME has already a macro for that).
having this class in haxe
class Foo {
#:property var bar:String;
}
I like this to be expanded into
class Foo {
private var bar:String;
public function setBar(_val:String):void {
this.bar = _val;
}
public function getBar():String {
return this.bar;
}
}
I read the corresponding docs but honestly I find them very confusing.
thanks
You might want to take a look at how tinkerbell resolves the same issue: https://github.com/back2dos/tinkerbell/wiki/tink_lang#wiki-accessors
This Type Builder example (pasted below for reference, but there's better description at the link) found in the Haxe Manual is a nice, simple example of adding a function to a Class.
Adding a property would be much the same. I added a trace(field) loop to help get a feel for how they're defined:
Main.hx
#:build(TypeBuildingMacro.build("myFunc"))
class Main {
static public function main() {
trace(Main.myFunc); // my default
}
}
TypeBuildingMacro.hx
import haxe.macro.Context;
import haxe.macro.Expr;
class TypeBuildingMacro {
macro static public function build(fieldName:String):Array<Field> {
var fields = Context.getBuildFields();
for (field in fields) { trace(field); }
var newField = {
name: fieldName,
doc: null,
meta: [],
access: [AStatic, APublic],
kind: FVar(macro : String, macro "my default"),
pos: Context.currentPos()
};
fields.push(newField);
return fields;
}
}
Note that Main.hx must invoke the macro with the #:build metadata, so the compiler knows to run the macro (which adds the function) before processing the Main class itself.
Lets say I have an already functioning Play 2.0 framework based application in Scala that serves a URL such as:
http://localhost:9000/birthdays
which responds with a listing of all known birthdays
I now want to enhance this by adding the ability to restrict results with optional "from" (date) and "to" request params such as
http://localhost:9000/birthdays?from=20120131&to=20120229
(dates here interpreted as yyyyMMdd)
My question is how to handle the request param binding and interpretation in Play 2.0 with Scala, especially given that both of these params should be optional.
Should these parameters be somehow expressed in the "routes" specification? Alternatively, should the responding Controller method pick apart the params from the request object somehow? Is there another way to do this?
Encode your optional parameters as Option[String] (or Option[java.util.Date], but you’ll have to implement your own QueryStringBindable[Date]):
def birthdays(from: Option[String], to: Option[String]) = Action {
// …
}
And declare the following route:
GET /birthday controllers.Application.birthday(from: Option[String], to: Option[String])
A maybe less clean way of doing this for java users is setting defaults:
GET /users controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)
And in the controller
public static Result users(Integer max, Integer page) {...}
One more problem, you'll have to repeat the defaults whenever you link to your page in the template
#routes.Application.users(max = 50, page = 0)
In Addition to Julien's answer. If you don't want to include it in the routes file.
You can get this attribute in the controller method using RequestHeader
String from = request().getQueryString("from");
String to = request().getQueryString("to");
This will give you the desired request parameters, plus keep your routes file clean.
Here's Julien's example rewritten in java, using F.Option: (works as of play 2.1)
import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
// …
}
Route:
GET /birthday controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])
You can also just pick arbitrary query parameters out as strings (you have to do the type conversion yourself):
public static Result birthdays(Option<String> from, Option<String> to) {
String blarg = request().getQueryString("blarg"); // null if not in URL
// …
}
For optional Query parameters, you can do it this way
In routes file, declare API
GET /birthdays controllers.Application.method(from: Long, to: Long)
You can also give some default value, in case API doesn't contain these query params it will automatically assign the default values to these params
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
In method written inside controller Application these params will have value null if no default values assigned else default values.
My way of doing this involves using a custom QueryStringBindable. This way I express parameters in routes as:
GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)
The code for Period looks like this.
public class Period implements QueryStringBindable<Period> {
public static final String PATTERN = "dd.MM.yyyy";
public Date start;
public Date end;
#Override
public F.Option<Period> bind(String key, Map<String, String[]> data) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
try {
start = data.containsKey("startDate")?sdf.parse(data.get("startDate") [0]):null;
end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null;
} catch (ParseException ignored) {
return F.Option.None();
}
return F.Option.Some(this);
}
#Override
public String unbind(String key) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
return "startDate=" + sdf.format(start) + "&" + "endDate=" + sdf.format(end);
}
#Override
public String javascriptUnbind() {
return null;
}
public void applyDateFilter(ExpressionList el) {
if (this.start != null)
el.ge("eventDate", this.start);
if (this.end != null)
el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate());
}
}
applyDateFilter is just a convienence method i use in my controllers if I want to apply date filtering to the query. Obviously you could use other date defaults here, or use some other default than null for start and end date in the bind method.