I defined an inner function here:
person(firstName, lastName){
fullName(){ //Is it possible to invoke this function outside the 'person' function?
return firstName + " " + lastName;
}
firstInitial(){
return firstName[0];
}
lastInitial(){
return lastName[0];
}
}
Next, I tried to invoke the "fullName" function from the "main" function:
void main() {
print(person("Rob", "Rock").fullName());
}
but it produced this error:
Uncaught TypeError: Cannot read property 'fullName$0' of undefined
Is it possible to invoke an inner function outside the scope where the function is defined?
You can declare the function outside the enclosing block:
void main() {
var fullName;
person(firstName, lastName){
fullName = () => "firstName: $firstName lastName: $lastName";
}
person("Rob", "Rock");
print(fullName());
}
or return it:
void main() {
person(firstName, lastName) => () => "firstName: $firstName"
"lastName: $lastName";
print(person("Rob", "Rock")());
}
If you want this syntax person("Rob", "Rock").fullName() you can return class instance:
class Res{
var _firstName, _lastName;
Res(this._firstName, this._lastName);
fullName() => "firstName: $_firstName lastName: $_lastName";
}
void main() {
person(firstName, lastName) => new Res(firstName,lastName);
print(person("Rob", "Rock").fullName());
}
Those functions can be invoked externally, the issue is that your program can't see them. Your function returns void, so the inner functions are invisible.
But what it looks like you're trying to do is define a class. So a simpler way to do it is
class Person {
var firstName, lastName;
Person(this.firstName, this.lastName);
get fullName => "$firstName $lastName";
firstInitial() => firstName[0];
lastInitial() { return lastName[0]; }
}
main() {
print(new Person("Rob", "Rock).fullName);
print(new Person("Robert", "Stone").lastInitial());
}
For illustration I used three different syntaxes for the three different functions, a getter, a lambda, and a full-blown function.
Related
I'm trying to implement an event callback directly in the constructor, but for some reason it does not compile and I do not understand what's the issue with my code.
abstract class Base {
final Future<bool>? onMagic;
Base({
this.onMagic
});
Future<void> doSomething() async {
if(onMagic != null) {
// does not work... why?
// final useMagic = await onMagic!();
onMagic?.then((magic) {
if(magic) print("TODO make something magical");
});
}
}
}
class RealMagic extends Base {
RealMagic() : super(
// Error: The argument type 'Future<bool> Function()' can't be assigned to the parameter type 'Future<bool>?'.
onMagic: () async => await _magic();
);
Future<bool> _magic() async {
return true;
}
}
I inlined the error above. If that's not possible which alternatives do I have to handle the optional callback?
The problem is with the type of the onMagic. It's not a Future<bool>, it should be a Future<bool> Function()?
abstract class Base {
final Future<bool> Function()? onMagic;
Base({this.onMagic});
Future<void> doSomething() async {
onMagic?.call().then((magic) {
if (magic) print("TODO make something magical");
});
}
}
class RealMagic extends Base {
RealMagic()
: super(
onMagic: () async => await _magic(),
);
static Future<bool> _magic() async { // Made this static so it can be accessed in the constructor
return true;
}
}
I have an example that works in dart before null safety that doesn't after upgrading to Null safety. I can't figure out what's going on.
It gives me the error
A value of type 'dynamic Function()?' can't be returned from the method 'doSomething' because it has a return type of 'dynamic Function()'
But I didn't define anything as Nullable.
typedef RandomFunction = Function();
class RegisteredFunctions {
Map<String, RandomFunction> types = {};
static final RegisteredFunctions _registry = RegisteredFunctions._init();
RegisteredFunctions._init() {}
factory RegisteredFunctions() {
return _registry;
}
void registerFunction(String name, RandomFunction func) {
types[name] = func;
}
RandomFunction doSomething(String id) => types[id]; //<---- gives error
}
void doStuff(){
print('Doing Something');
}
void main() {
RegisteredFunctions functions = RegisteredFunctions();
functions.registerFunction('func1', doStuff);
functions.doSomething('func1')();
}
For anyone else trying to figure it out.. this fixed it.
typedef RandomFunction = Object? Function();
class RegisteredFunctions {
Map<String, RandomFunction> types = {};
static final RegisteredFunctions _registry = RegisteredFunctions._init();
RegisteredFunctions._init() {}
factory RegisteredFunctions() {
return _registry;
}
void registerFunction(String name, RandomFunction func) {
types[name] = func;
}
// RandomFunction doSomething(String id) => types[id]; // <----- Doesn't work
// RandomFunction doSomething(String id) => types[id]!; // <----- Works
RandomFunction doSomething(String id) { // <----- Works better
RandomFunction? func = types[id];
if (func != null) {
return func;
} else {
return (){};
}
}
}
void doStuff(){
print('Doing Something');
}
void doOtherStuff(){
print('Doing Something else');
}
void main() {
RegisteredFunctions functions = RegisteredFunctions();
functions.registerFunction('func1', doStuff);
functions.registerFunction('func2', doOtherStuff);
functions.doSomething('func1')();
functions.doSomething('func2')();
}
I’d like to pass the class User as second argument to the load-function.
Maybe someone knows how?
class App {
Map<String, List<Model>> models = {
'users': List<User>()
};
App() {
load('users');
}
void load(resource) {
Directory directory = Directory.fromUri(Uri(path: './app/data/' + resource));
for (FileSystemEntity file in directory.listSync(recursive: false)) {
Map<String, dynamic> fileContent = jsonDecode(File(file.uri.path).readAsStringSync());
models[resource].add(User.fromJson(fileContent));
}
}
}
You can't.
You can pass a Type object as argument, or a type as type argument (load<T>(resource) { ... }), but neither will allow you to call User.fromJson on the type.
What you can do is to pass the User.fromJson function as an argument (or, if that's a constructor, pass (x) => User.fromJson(x) as argument). That is:
void load(String resource, Object? fromJson(Map<String, dynamic> json)) {
...
map[resoruce].add(fromJson(fileContent));
}
and then
load("someName", (map) => User.fromJson(map));
I want to wrote method which call all function in class:
class Example extends MyAbstractClass {
void f1(){...}
void f2(){...}
void f3(){...}
Example(){
callAll();//this call f1(), f2() and f3().
}
}
I have problem in this part of code:
reflectClass(this.runtimeType).declarations.forEach((Symbol s, DeclarationMirror d) {
if (d.toString().startsWith("MethodMirror on ")) {
String methodName = d.toString().substring(16).replaceAll("'", "");
print(methodName);
// How to call function by name methodName?
}
});
instead of
if (d.toString().startsWith("MethodMirror on ")) {
you can use
if (d is MethodMirror) {
You need an InstanceMirror of an instance of the class. I think in your case this would be
var im = reflect(this).invoke(d.simpleName, []);
im.declarations.forEach((d) ...
see also How can I use Reflection (Mirrors) to access the method names in a Dart Class?
Using dson you can do:
library example_lib;
import 'package:dson/dson.dart';
part 'main.g.dart';
#serializable
class Example extends _$ExampleSerializable {
Example() {
_callAll();
}
fn1() => print('fn1');
fn2() => print('fn2');
fn3() => print('fn3');
fn4() => print('fn4');
_callAll() {
reflect(this).methods.forEach((name, method) {
if(name != '_callAll') this[name]();
});
}
}
main(List<String> arguments) {
_initMirrors();
new Example();
}
How can I set another Class as a Class constructor argument?
class MyClass {
String message = 'myClass';
void print() {
print(this.message);
}
}
class TestClass {
var myClass;
TestClass(???) {
this.myClass = ???(); // ???
}
void debug() {
print('DEBUG: ');
this.myClass.print();
}
}
main() {
MyClass myClass;
testClass(myClass);
}
You can't (at least not now). Your best option is to pass a builder function into the constructor.
class MyClass {
var clazzBuilder;
MyClass(this.clazzBuilder);
doStuff() {
var instance = clazzBuilder();
:
}
}
and then use it like this
var myTest = new MyClass(() => new Test());
var myProd = new MyClass(() => new Prod());
Note that the Dart team is planning to add both class concept (.type) and reflection to the language.
What do you want actually do? Often people try to apply paradigms from some languages in some other languages which isn't the best way to do some things.
Since print is an instance method and not a static method, you don't need to pass a class itself to TestClass, just an instance of it. Your program can be fixed like so:
class MyClass {
String message = 'myClass';
void print() {
print(this.message);
}
}
class TestClass {
var myClass;
TestClass(MyClass myClass) {
this.myClass = myClass;
}
void debug() {
print('DEBUG: ');
this.myClass.print();
}
}
main() {
MyClass myClass = new MyClass();
testClass(myClass);
}
Or, more idiomatically:
class MyClass {
String message = 'myClass';
void print() => print(message);
}
class TestClass {
var myClass;
TestClass(this.myClass);
void debug() {
print('DEBUG: ');
myClass.print();
}
}
main() {
testClass(new MyClass());
}