I've got a method that does the default approach when an error occurs and simply dumps the error to the user's computer screen:
void onError(FlutterErrorDetails details) => FlutterError.dumpErrorToConsole(details);
Now, the user is invited to override this method, of course, but when the time comes and an error does occur, I want to know if the method was overridden or not. I can't figure out how one would do this however.
In Dart, functions are first-class objects, and so is there not a way to 'record' what the method was as the class defines it, and what it is now when the class object is instantiated? Something like:
static final FlutterExceptionHandler _dumpError = (FlutterErrorDetails details) => FlutterError.dumpErrorToConsole(details);
if (onError == _dumpError) {
_prevOnError(details);
} else {
onError(details);
}
Now the above doesn't work, of course. onError does not equal _dumpError. I even tried this:
static final FlutterExceptionHandler _dumpError = FlutterError.dumpErrorToConsole(details);
void onError(FlutterErrorDetails details) => _dumpError;
Now this actually works in that, when an error occurs, onError() fires and dumps the error to the console. However, it's not quite right as the comparison (==) would, again, return false. How do I make it true?: onError == _dumpError
Is there a way to do this, you think? Is there a way to compare the 'contents' of two functions??
I dunno. I'm grasping at straws at this point.
Cheers.
"I want to know if the method was overridden or not. I can't figure out how one would do this however". The point of OOP is that you shouldn't ever need to care, or even know, if that had happened. What's your actual use case?
Related
I got a strong background in C# and Javascript and there is nothing I am not getting on Dart with Futures :
Say I got a Future like this :
scoreFile.exists().then((r) => {
if (r){
List<ScoreRow> previousScores = await scoreFile.readAsString();
scores = jsonDecode(previousScores);
}
});
I know this is not allowed because I need to make my callback a foo() function. But why clutter the space with a code to be used only in this place ? I mean, I really need to create as many little functions as I have callbacks ?
I wouldn't do so with really complex processing, (which would be untestable if not put in a proper function) but for such a simple process ?
Or maybe Dart design is "there is no such thing as simple code not to be tested"
Because from a syntaxical point of view, my function already exists, she is just anonymous : she is stored in braces :)
Thank you for your insight :)
I'm not entirely sure what the problem is here.
Your code mixes async and non-async code, which is usually something to avoid unless absolutely necessary (which it rarely is).
You could perhaps write the code as:
if (await scoreFile.exists()) {
scores = jsonDecode(await scoreFile.readAsString());
}
or you could continue doing what you are doing (fixing syntax and type issues):
scoreFile.exists().then((r) async {
if (r) {
var previousScores = await scoreFile.readAsString();
return jsonDecode(previousScores);
}
}).then((scores) {
// use the scores variable.
});
If you use the then approach, then yes, you will have to make a lot of little callbacks because that's how it works. If you use the async/await syntax, those callbacks will be made for you.
First, the context of what I'm doing. I am running an HttpServer which is handling HttpRequests.
HttpServer.bind(ADDRESS, PORT).then((HttpServer server) {
listenSubscription = server.listen(onRequest);
});
void onRequest(HttpRequest request) {
//handle request here
}
I'd like to add some logging to all this, and due to the asynchronous nature of it all, want to add some identifying marker to the requests (so I can match up the request receipts with the responses, fer example). The code inside of onRequest() calls a bunch of other functions to do different things (handle GET vs POST requests, etc.), so simply generating an id at the top is a cumbersome solution as I'd have to pass it around through all those other function calls. I am, however, already passing around the HttpRequest object, so I thought it would be nice to throw an id field on it, just like you would in Javascript, except that Dart doesn't work that way.
Thoughts then went to subclassing the HttpRequest class, but converting the HttpRequest object the onRequest() method receives seemed like much more trouble and overhead than my needs required.
So I ask, is there any idiomatic Dart way attach some data to an existing object? If there isn't something idiomatic, what is the simplest (both in code and runtime complexity) way you can think of to accomplish this?
Well, there's an Expando, but I don't know the performance implications.
Something like:
// somewhere top level. Create this once.
final loggingId = new Expando();
...
// inside of onRequest
loggingId[request] = generateId();
...
// later inside log()
print(loggingId[request]);
Expandos are like weak-reference maps, from my understanding.
In the following example, main is allowed to call a sniff function on Dog that I would prefer would somehow break. If I say exactly what a Dog can do, but somehow the client knows more and can get the object to do more with that special knowledge - I think that is an encapsulation leak. I don't necessarily want it to die in the general case, but is there a flag or way to run that would enforce that only methods be called if they exist. I know the language supports the knowledge that something is wrong since the Dart Editor displays a warning: The method 'sniff' is not defined for the class 'Dog'. Even when run with --checked flag, this runs fine.
So suppose similar code were invoked by a test. Is there a flag in Dart or some code to cause it to fail when the test is run?
abstract class Dog {
void run();
void bark();
}
class BigDog implements Dog {
void run() => print("Big dog running");
void bark() => print("Woof");
void sniff() => print("Sniff");
}
main() {
Dog bd = new BigDog();
bd.run();
bd.bark();
bd.sniff();
}
You should ensure to run the tests in checked mode dart -c testfile.dart then type annotations are taken into account. You shouldn't use checked mode in production though because it slows down your application.
This isn't possible. The problem is that your instance really is a BigDog; and therefore it really has a sniff method. An important goal in Dart is that type annotations do not affect runtime behaviour; therefore your Dog annotation is unable to change the behaviour.
The tooling is able to highlight this because it does use the type annotations.
This sort of question comes up a lot in the Dart bug tracker; but it would be a pretty fundamental change to allow type annotations to change behaviour, so it's not something I expect would ever be considered; confusing as it might be. See here for some more info on this.
I'm new to Dart, so maybe I'm missing something here:
This works:
In my main(), I have this:
var a = _someFunction;
var b = _someFunction;
print("${a == b}"); // true. correct!
Where _someFunction is another top-level function.
This does NOT work: (at least not how I'm expecting it to)
Given this class...
class Dummy {
void start() {
var a = _onEvent;
var b = _onEvent;
print(a == b); // false. ???????
}
void _onEvent() {
}
}
Instantiating it from main() and calling its start() method results in false. Apparently a new instance of some function or closure object is created and returned whenever my code obtains a reference to _onEvent.
Is this intentional behaviour?
I would expect that obtaining multiple references to the same method of the same instance returns the same object each time. Perhaps this is intended for some reason. If so; what reason? Or is this a bug/oversight/limitation of VM perhaps?
Thanks for any insights!
Currently, the behaviour seems to be intentional, but the following defect is open since May 2012: https://code.google.com/p/dart/issues/detail?id=144
If I were to guess, I'd say that setting "var a = _onEvent;" creates a bound method, which is some sort of object that contains both the function as well as this. You are asking for bound methods to be canonicalized. However, that would require the team to create a map of them, which could lead to worries about memory leaks.
I think they made "var a = _someFunction;" work early on because they needed static functions to be constants so that they could be assigned to consts. This was so that they could write things like:
const logger = someStaticLoggingFunction;
This was in the days before statics were lazily evaluated.
In any case, I would say that comparing closures for equality is a edge case for most languages. Take all of the above with a grain of salt. It's just my best guess based on my knowledge of the system. As far as I can tell, the language spec doesn't say anything about this.
Actually, now that I've read (https://code.google.com/p/dart/issues/detail?id=144), the discussion is actually pretty good. What I wrote above roughly matches it.
In the bad old days in my codebase we relied quite heavily on event requeuing, which I suspect worked due to implementation details in ICEfaces or MyFaces rather than standard-specified behavior. One thing we used to do frequently was this kind of thing:
<ice:inputText value="#{bb.frequency}" valueChangeListener="#{bb.valueChanged}"/>
The goal is to arrange for retune to be called after setFrequency whenever the frequency changes.
Then we had some fairly disgusting code in the backing bean which would requeue the event. It usually looked something like this:
class BB {
// this happens first, thanks to UPDATE_MODEL_VALUES
public void setFrequency(Frequency f) {
this.model.f = f;
}
public void valueChanged(ValueChangeEvent event) {
if (event.getOldValue().equals(event.getNewValue())
return; // nothing changed, so leave
if (FacesContext.getCurrentInstance().getPhaseId() != INVOKE_APPLICATION) {
OurMagicEventUtils.requeueEvent(event, INVOKE_APPLICATION);
}
else {
// do the post-setter work here (the setter happened recently during
// UPDATE_MODEL_VALUES so we're up-to-date by here
this.model.retune();
}
}
}
This isn't a good way to live. I haven't found a reliable way to requeue events for later phases and it clearly isn't the kind of thing people do. I see two solutions:
Move the retune intelligence to the BB#setFrequency method.
I can't get away with this in many cases because I'm directly addressing a lower-level model class and I don't want to disturb its behavior for other clients.
Create a custom component and move the logic into the setFoo method there.
I don't love this because there are a lot of issues with Mojarra and custom components when embedded in other containers. It also seems like overkill for what I need to do—I literally just need to call retune after setting some properties.
Create backing beans for everything. Delegate most methods directly to the inner thing, but catch setFoo and perform the retune there. This is very similar to what we used to do, and it means a lot of boilerplate, wrappers, and glue code, so I don't love it.
In my mind I imagine something like this:
<ice:inputText value="#{bb.frequency}" afterChange=#{bb.retune}"/>
but that obviously doesn't work, nor would attaching an <f:actionListener> since that requires a class name but has no association to whatever you're currently doing, and besides it can only be set on UICommands which UIInputs are not.
What's the elegant/correct way to solve this dilemma?
As you're using JSF2 already, just use <f:ajax>.
<ice:inputText value="#{bb.frequency}">
<f:ajax listener="#{bb.retune}"/>
</ice:inputText>
with
public void retune(AjaxBehaviorEvent event) { // Note: the argument is optional.
// ...
}
This will be invoked during invoke action phase when the HTML DOM change event has occured.