Define function signature for a class member in Dart - dart

I would like to specify the signature of a function used as a class field.
Here is an example:
class Space<PointType>
{
// num distance(PointType, PointType); This does not work
final distance; // This works but dystance types are not defined
Space(num this.distance(PointType, PointType));
}
I know I can use typedef to define a callback interface. However this does not seem to work within generics.
Any suggestions?

You can use generics with typedef. In your case :
typedef num ComputeDistance<E>(E p1, E p2);
class Space<PointType> {
final ComputeDistance<PointType> distance;
Space(this.distance);
}

You can use a typedef to declare the signature of a function used in a class field. I am not entirely sure I follow your specific example, so I'll keep the discussion generic.
Here is the syntax for using a typedef:
typedef functionReturnType nameOfTypedef(ParamType paramName);
Here is a concrete example:
typedef String MyFuncType(int x, int y);
This example defines MyFuncType to return a String and take two int arguments.
class MyClass {
MyFuncType func; // Matches a func that returns a String and take 2 int arguments.
...
}
You can read a fuller discussion about using typedefs at https://github.com/dart-lang/cookbook/blob/basics/basics.asciidoc#using-typedef-to-declare-a-function-signature.

Related

class parameter or class identifier query

I am new in Dart and works on an app that has a class look like this:
abstract class BaseUseCase <In,Out> {}
My question is then, what is In and Out?
In and Out are type arguments. They are used to allow the code in the class to use objects of an unknown type while remaining consistent and type-safe.
For example, say you wanted to have a method in a class that would take a list of any type, perform a string conversion operation on every element, and then return a strongly typed map of results:
class Stringifier<T> {
Map<T, String> stringify(List<T> input) =>
{for (final entry in input) entry: input.toString()};
}
void main() {
Stringifier<int>().stringify([1, 2, 3]);
// Result: <int, String>{1: '1', 2: '2', 3: '3'}
}
Note that the return type and input argument type use the generic T type. This ensures that only a list of the given type can be passed in, and that the resultant map will have the correct key type.
Type arguments can be used in other declarations as well, such as function declarations - indeed, the example above can be simplified, and declared outside a class:
Map<T, String> stringify(List<T> input) { /* ... */ }
More information on generics can be found in the Dart Language Tour, as well as in the "Generics" section of the Dart 2 language specification.

Get pointer to a struct from a Dart_NativeArguments struct in C

I'm trying to wrap a C library using Dart. I call into a C function from dart and pass in the arguments through a Dart_NativeArguments struct in C:
void _sayHello(Dart_NativeArguments arguments) {
string from;
Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0));
if (Dart_IsString(seed_object)) {
const char* seed;
HandleError(Dart_StringToCString(seed_object, &seed));
from = seed;
}
num = (int)Dart_GetNativeArgument(arguments, 1);
Dart_SetReturnValue(arguments, HandleError(Dart_NewStringFromCString(sayHello(from, num).c_str())));
}
In Dart, I call the function and pass in the necessary arguments
String sayHello(String from) native "sayHello";
main() {
print(sayHello("Dart"));
}
I was wondering how I could pass in pointers (to a struct I made) instead of just strings and ints as arguments. There are functions in Dart to convert Dart_Handles into Strings and ints but not pointers. What is the internal structure of the Dart_Handle and how would I go about converting it back to a pointer? For example:
Dart code:
String sayHello(info from) native "sayHello";
class info
{
String message;
int num;
}
main() {
info tester = new info();
tester.message = "Dart";
tester.num = 2;
print(sayHello(tester));
}
C Code:
void sayHello(Dart_NativeArguments arguments) {
/*What do I do here to get back a pointe to the struct/class I passed
in as an argument in Dart?*/
}
Your Dart_NativeArguments will consist of just one item, which will be an instance - the instance of the class info that you created with new info(). You can test whether it's an instance with bool Dart_IsInstance(Dart_Handle object). So what you have is an handle to an instance of info. This allows you to access its instance fields (message and num) to get and set them, using Dart_GetField and Dart_SetField.
Dart_Handle instance = Dart_GetNativeArgument(arguments, 0);
Dart_Handle message_handle = Dart_GetField(retobj, NewString("message"));
char* message;
Dart_StringToCString(message_handle, &message);
Dart_Handle number_handle = Dart_GetField(retobj, NewString("num"));
int64_t number;
Dart_IntegerToInt64(number_handle, &number);
// message contains the string, number contains the number
// use them, copy them etc
I know this is just an example, but it might be easier to redefine sayHello to take 2 arguments (a string and an int) rather than passing an object instance. There isn't a way to access the fields of a class in one step, you need to access them individually. Consider these two versions of the Dart code, one passing an object instance and one just the values. The second version is simpler at the Dart and C side (no GetField steps). The first version is more powerful, though, because you could update the fields using SetField, which you couldn't in the second.
class Info {
String message;
int num;
Info(this.message, this.num);
}
version1() {
sayHelloV1(new Info('Dart', 2));
}
version2() {
sayHelloV2('Dart', 2);
}
If your C API requires you to pass in a struct you will have to create that in your C code by copying the values you extract using Dart_IntegerToInt64etc into it, then pass the pointer to your C struct to the API.
If your API is very precise about the packing/padding of the data into the struct, you could use Dart typed_data to pack the Dart types into a ByteData and pass the underlying byte array.

Does FutureOr<T> have a reified type of Future<T> / <T>?

I have a class in AngularDart as followings:
abstract class Validator {
Map validate(AbstractControl c);
}
Looking closely, this used to be (before we added strong-mode support):
abstract class Validator {
validate(AbstractControl c);
}
The issue that it technically supports returning a Future or Map.
I'd like to refactor this and properly type it using FutureOr:
abstract class Validator {
FutureOr<T> validate(AbstractControl c);
}
Will I be able to use an is check at runtime? (In DDC and dart2js)
void runValidator(Validator v) {
var result = v.validate(...);
if (result is Future) {
// async...
} else {
// sync...
}
}
Am I thinking about this correctly?
EDIT: As mentioned below, I mean
if (result is Future<T>) {
} else if (result is T) {
}
One more question, would validate match these two typedefs:
Future<Map> AsyncValidate(AbstractControl c);
Map SyncValidate(AbstractControl c);
Yes, you can do result is Future<Map>. The actual value returned by the validate method is either a Future or it's not. The static type of the function doesn't affect that, and since FutureOr<Map> isn't an actual class, you can't have an object that is "a FutureOr". It's either a real Future<Map> or it's a Map.
For the second question, that depends on what yo mean by "match".
You can override the method with a method that returns either Map or FutureMap:
abstract class Validator {
FutureOr<Map> validate(abstractControl c);
}
class AsyncValidator extends Validator {
Future<Map> validate(AbstractControl c) {...}
}
class SyncValidator extends Validator {
Map validate(AbstractControl c) {...}
}
That is, you can use one of the function types you mention as a Validator.validate, but not in the other direction.
typedef FutureOr<Map> Validate(AbstractControl c);
typedef Future<Map> AsyncValidate(AbstractControl c);
typedef Map SyncValidate(AbstractControl c);
Validator v = ...;
Validate f0 = v.validate; // Safe.
AsyncValidate f1 = v.validate; // BAD assignment.
SyncValidate f2 = v.validate; // BAD assignment.
Map syncValidate(AbstractControl c) { ... }
Future<Map> asyncValidate(AbstractControl c) { ... }
v = syncValidate; // Good assignment.
v = asyncValidate; // Good assignment.
In practice, the concrete validate method of the validator v will probably be assignable to one of f1 or f2, but its static type doesn't say which one, so both are considered bad assignments.
You should only very rarely have a non-abstract method that is declared as returning FutureOr. In most cases, it's better to just always return a Future or a non-Future, and declare the method as such. Then you can always use the function as returning FutureOr if you need to, but use the more precise type in cases where you need it.

How to create private variables in Dart?

I want to create a private variable but I cannot.
Here is my code:
void main() {
var b = new B();
b.testB();
}
class A {
int _private = 0;
testA() {
print('int value: $_private');
_private = 5;
}
}
class B extends A {
String _private;
testB() {
_private = 'Hello';
print('String value: $_private');
testA();
print('String value: $_private');
}
}
When I run this code, I get the following result:
String value: Hello
int value: Hello
Breaking on exception: type 'int' is not a subtype of type 'String' of 'value'.
Also I not get any error or warnings when editing this source code.
How can I create a private variable in Dart?
From Dart documentation:
Unlike Java, Dart doesn’t have the keywords public, protected, and private. If an identifier starts with an underscore _, it’s private to its library.
Libraries not only provide APIs, but are a unit of privacy: identifiers that start with an underscore _ are visible only inside the library.
A few words about libraries:
Every Dart app is a library, even if it doesn’t use a library directive. The import and library directives can help you create a modular and shareable code base.
You may have heard of the part directive, which allows you to split a library into multiple Dart files.
Dart documentation "libraries-and-visibility"
Privacy in Dart exists at the library, rather than the class level.
If you were to put class A into a separate library file (eg, other.dart), such as:
library other;
class A {
int _private = 0;
testA() {
print('int value: $_private'); // 0
_private = 5;
print('int value: $_private'); // 5
}
}
and then import it into your main app, such as:
import 'other.dart';
void main() {
var b = new B();
b.testB();
}
class B extends A {
String _private;
testB() {
_private = 'Hello';
print('String value: $_private'); // Hello
testA();
print('String value: $_private'); // Hello
}
}
You get the expected output:
String value: Hello
int value: 0
int value: 5
String value: Hello
In dart '_' is used before the variable name to declare it as private. Unlike other programming languages, here private doesn't mean it is available only to the class it is in, private means it is accessible in the library it is in and not accessible to other libraries. A library can consists of multiple dart files as well using part and part of. For more information on Dart libraries, check this.
The top answer as of now is definitely correct.
I'll try to go into more detail in this answer.
I'll answer the question, but lead with this: That's just not how Dart is intended to be written, partly because library-private members make it easier to define operators like ==. (Private variables of a second object couldn't be seen for the comparison.)
Now that we've got that out of the way, I'll start out by showing you how it's meant to be done (library-private instead of class-private), and then show you how to make a variable class-private if you still really want that. Here we go.
If one class has no business seeing variables on another class, you might ask yourself whether they really belong in the same library:
//This should be in a separate library from main() for the reason stated in the main method below.
class MyClass {
//Library private variable
int _val = 0;
int get val => _val;
set val(int v) => _val = (v < 0) ? _val : v;
MyClass.fromVal(int val) : _val = val;
}
void main() {
MyClass mc = MyClass.fromVal(1);
mc.val = -1;
print(mc.val); //1
//main() MUST BE IN A SEPARATE LIBRARY TO
//PREVENT MODIFYING THE BACKING FIELDS LIKE:
mc._val = 6;
print(mc.val); //6
}
That should be good. However if you really want private class data:
Though you technically aren't allowed to create private variables, you could emulate it using the following closure technique. (HOWEVER, you should CAREFULLY consider whether you really need it and whether there is a better, more Dart-like way to do what you're trying to accomplish!)
//A "workaround" that you should THINK TWICE before using because:
//1. The syntax is verbose.
//2. Both closure variables and any methods needing to access
// the closure variables must be defined inside a base constructor.
//3. Those methods require typedefs to ensure correct signatures.
typedef int IntGetter();
typedef void IntSetter(int value);
class MyClass {
IntGetter getVal;
IntSetter setVal;
MyClass.base() {
//Closure variable
int _val = 0;
//Methods defined within constructor closure
getVal = ()=>_val;
setVal = (int v) => _val = (v < 0) ? _val : v;
}
factory MyClass.fromVal(int val) {
MyClass result = MyClass.base();
result.setVal(val);
return result;
}
}
void main() {
MyClass mc = MyClass.fromVal(1);
mc.setVal(-1); //Fails
print(mc.getVal());
//On the upside, you can't access _val
//mc._val = 6; //Doesn't compile.
}
So yeah. Just be careful and try to follow the language's best-practices and you should be fine.
EDIT
Apparently there's a new typedef syntax that's preferred for Dart 2. If you're using Dart 2 you should use that. Or, even better, use inline function types.
If you use the second, it will be less verbose, but the other problems remain.

How to reference static classes in Actionscript

I apologize in advance for the newbiness of this question; I think I'm not grasping the basics of Actionscript but haven't been able to find an answer elsewhere.
What I want is some global constants like one would have in C++. In C++, I would simply have a file where I would #define MAP_HEIGHT 20, or something like that, and they would be globally accessible when I included the file at the top. In Actionscript, I've tried making a static class instead, like so:
package
{
public class Settings {
public const mapx:int = 20;
public function Settings() {}
}
}
But when I try to reference it in my code with colon syntax
var a:int = Settings::mapx;
I get the error "[Fault] exception, information=TypeError: Error #1034: Type Coercion failed: cannot convert Settings$ to Namespace."
I tried dot syntax:
var a:int = Settings.mapx;
and got a different error, "Access of possibly undefined property mapx through a reference with static type Class."
But what I really want is a file of global static variables, like in C++, and can't find a way to do it in Actionscript.
Mark variables, constants, and functions with the static keyword, as in:
package
{
public class MathUtil
{
public static const PI:Number = 3.141592653589;
public static function deg2rad(angle:Number):Number
{
angle = !isNaN(angle) ? (angle) : (0);
return angle * PI / 180;
}
}
}
Then you may use dot notation.
var pi:Number = MathUtil.PI;
var angle:Number = MathUtil.deg2rad(45);
From ActionScript 3.0 Reference for the Adobe Flash Platform: Statements, Keywords & Directives
Usage
class someClassName {
static var varName;
static const kName;
static function methodName() { }
}
You can use static in class definitions only, not in interface
definitions.
Static class members are not inherited. You cannot refer to a static
class member using the name of a subclass, as you can in Java or C++.
You can, however, refer to a static variable or method within a class
or subclass, without using any qualifier. See the example below.
You cannot use the super statement or the this keyword inside a static
method.

Resources