So I want to extend the dictionary class. Everything works so far except that in some of my methods that need to reference the dictionary's content I make a call like:
this[ key ]
It doesn't like that. It just tells me that there's no property 'key'. Is there a way to way to access the data within this class?
Also, I'm using an integer for the key.
Edit: I've found that the same behavior happens when you extend Array.
var myArray : Array = new Array();
trace( myArray[ 0 ] );
var myArrayExtender : ArrayExtender = new ArrayExtender();
trace( myArrayExtender[ 0 ] );
Where in this case, myArray returns "undefined" and myArrayExtender throws error 1069. ArrayExtender is an empty class that extends Array and calls super() in the constructor.
from what you say, i am quite sure you did not declare ArrayExtender as dynamic
in ECMAscript array access and property access are semantically equivalent ... #1069 happens, if you access an undefined property, on a sealed class, because thes do not allow adding properties at runtime ...
same thing for the Dictionary ...
greetz
back2dos
Related
I understand that dart uses reference types, and I'm wondering if there's a way to declare a variable as a sub-property of a property where modifying that sub-property doesn't propagate back to the original property.
I have a Foo class with a property (bars) that contains a List<Bar>. I have a method (_getBarListCurrent) that accepts an instance of Foo.
_getBarListCurrent is supposed to update the List<Bar>, and then pass both the Foo and a separate List<Bar> to a web service method to update the Foo if the list has been changed. So the web service method checks both the solo List<Bar> and the list within the foo for equality.
I tried to do this by declaring a variable within _getBarListCurrent for newBars which is equal to the List<Bar> in the Foo, then modifying bars, and then passing both the Foo and newBars to the web service.
However, any changes made to newBars also get updated in Foo.bars, so the equality check in the web service method always returns true, and that method quits without updating the web service.
Is there a way I can declare newBars and modify it so I still have an instance of Foo.bars that remains unchanged (so I can compare the old and new value before attempting to change the web service)? I've tried declaring the Foo again within the method as originalFoo but any updates to newBars also get updated in originalFoo (even if I mark it as final).
Here's how the method looks right now:
Future<Foo> _getBarListCurrent(Foo foo) async {
List<Bar>? newBars = foo.bars;
final Foo originalFoo = foo;
if (x) {
// add some items to the newBars list
}
_fooService.updateBars(foo: originalFoo, bars: newBars);
}
You have to have to different lists to be able to modify one and not the other.
You can make the copy at whichever point best matches your use-case.
The simple version is to change Foo to copy on read:
class Foo {
List<Bar>? _bars;
List<Bar>? get bars {
var bars = _bars;
return bars == null ? null : [...bars];
}
}
Alternatively, you can make the copy where you intend to modify the list:
Future<Foo> _getBarListCurrent(Foo foo) async {
var bars = foo.bars;
List<Bar>? newBars = null ? null : [...bars];
// ...
My requirement is to get a NEW instance every time when I access the value in a MAP.
MyObject {
def type
}
def myMap = [
"key1" : new MyObject()
]
def obj1 = myMap.get("key1")
def obj2 = myMap.get("key1")
Can obj1 and obj2 be two different instances?
How will it behave if executed/accessed parallelly?
don't know what your use case is, but I guess I have the answer to your question:
def myMap = [
"key1" : new MyObject()
]
Just first instantiates a new object and then stores this object in the map. So every time you access it, you get the same object.
To create the behavior you describe, you need to add something dynamic to your map - a closure!
def myMap = [
"key2" : {-> new MyObject()}
]
but now a myMap.get("key2") still returns always the same - a closure. But if you execute it by calling myMap.get("key2")() (or short myMap.key2) you get a different object each time!
Unfortunately, this is a close as you will get. I hoped to do a trick with a key called getKey3 - I hoped that Groovy would call this "getter" when accessing key3 but this seems not to be the case.
There are other "tricks" in Groovy which could help you to achieve your goal (like MetaProgramming) but I guess there is a better solution if we would know your use case.
I'm trying to 'port' some script to the Dart. To learn how everything work etc.
But there is a problem - in JavaScript we can set and get any variable in the object.
In Dart we have a Map class. And I have no idea how to use it (there is not so many help from Dart API Reference).
Currently I have:
Map settings;
//Then I get an dynamic result of a function that gives either null or object.
settings = result ?? {};
settings.someVar = 5;
And this code produces the following error:
"The setter 'someVar' is not defined for the class 'Map'."
Of course I can just 'invent' a new class Settings, but is there any other solutions?
With a Map, you get and put values with the [] and []= operators. So in this case you would use it like so;
settings['someVar'] = 5;
You can also use the addAll method;
settings.addAll({'someVar': 5, 'someOtherVar': 10});
Dart API References: operator [], operator []=, addAll
I wish to have the sub-classes of a super-class "registered" by an arbitrary name - whenever I declare a sub-class I wish to also have it entered into the super-class.sub Map.
Is there any way to accomplish this outside of main()?
// base class
class Mineral{
final String formula;
static Map<String,Mineral> sub = {}
Mineral( this.formula );
}
// sub class - declare and register
class Mica extends Mineral{
Mica( String formula ) : super( formula );
}
Mineral.sub['mica'] = Mica; // oops!
when I run this, I get
Error: line 10 pos 1: unexpected token 'Mineral' Mineral.sub['mica'] = Mica;
assuming that executable code is not allowed outside main().
cannot put within the super-class since other sub-classes may declared later, outside the library.
Dart has no way to run code as part of a library being loaded.
Executable code can only be put inside methods, or in field initializers, and static field initializers are lazy so they won't execute any code until you try to read them.
This is done to ensure quick startup - a Dart program doesn't have to execute any code before starting the main library's "main" method.
So, no, there is no way to initialize something that isn't constant before main is called.
Either
Mineral.sub['mica'] = new Mica();
or
static Map<String,Type> sub = {};
When you assign Mica you assign the Type Mica. new Mica() is an instance of Mica that is of the kind Mineral and can be assigned to the map you declared.
edit
Maybe you want to initialize the sub map:
static Map<String,Mineral> sub = {'mica': new Mica()};
hint: the semicolon is missing in this line in your question.
I want to do this in Actionscript:
typeof(control1) != typeof(control2)
to test if two objects are of the same type. This would work just fine in C#, but in Actionscript it doesnt. In fact it returns 'object' for both typeof() expressions because thats the way Actionscript works.
I couldn't seem to find an alternative by looking in the debugger, or on pages that describe typeof() in Actionscript.
Is there a way to get the actual runtime type?
The best way is to use flash.utils.getQualifiedClassName(). Additionally, you can use flash.utils.describeType() to get an XML document the describes more about the class.
Actionscript 3 has an is operator which can be used to compare objects. Consider the following code:
var mySprite:Sprite = new Sprite();
var myMovie:MovieClip = new MovieClip();
trace(mySprite is Sprite);
trace(myMovie is MovieClip);
trace(mySprite is MovieClip);
trace(myMovie is Sprite);
Which will produce the following output:
true
true
false
false
This will work for built-in classes, and classes you create yourself. The actionscript 2 equivalent of the is operator is instanceof.
You'll want to use the Object.prototype.constructor.
From the documentation:
dynamic class A {}
trace(A.prototype.constructor); // [class A]
trace(A.prototype.constructor == A); // true
var myA:A = new A();
trace(myA.constructor == A); // true
(Conveniently, this is also how to check types in javascript, which is what originally led me to this in the docs)
So, to test this out before I posted here, I tried it in an app I have, in a class called Player. Since the prototype property is static, you can't call it using "this" but you can just skip the scope identifier and it works:
public function checkType():void {
trace(prototype.constructor, prototype.constructor == Player);
// shows [class Player] true
}
Is there a way to get the actual runtime type?
Yes.
var actualRuntimeType:Class = Object(yourInstance).constructor;
Some other answers already refer to .constructor, but you can't always directly access .constructor in ActionScript 3. It is only accessible on dynamic classes, which most classes are not. Attempting to use it on a regular class will cause a compile-time error under the default settings.
However, because every class inherits from Object, which is dynamic, we can look up their .constructor property just by casting an instance to Object.
Therefore if we are not interested in subclasses, we can confirm that two instances are of exactly the same class by simply evaluating this:
Object(instanceA).constructor === Object(instanceB).constructor;
I learned of this from the post "Get the class used to create an object instance in AS3" by Josh Tynjala.
A even simpler alternative that also works for me is just:
var actualRuntimeType:Class = yourInstance["constructor"];
The runtime is entirely capable of giving you the .constructor, it's just that the compiler complains if you use that syntax. Using ["constructor"] should produce the same bytecode, but the compiler isn't clever enough to stop you.
I included this second because it hasn't been tested anywhere except my current Flash environment, whereas several users have said that the method described above works for them.
If you want to account for inheritance, then you might want to try something like this:
if (objectA is objectB.constructor || objectB is objectA.constructor)
{
// ObjectA inherits from ObjectB or vice versa
}
More generally, if you want to test whether objectA is a subtype of objectB
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
...
if (objectA is getDefinitionByName(getQualifiedClassName(objectB)))
{
...
}
Object obj = new Object();
Object o = new Object();
if(o.getClass().getName().endsWith(obj.getClass().getName())){
return true;
}else{
return false;
}