Nulling objects passed as parameters, garbage collection? - actionscript

If I create a new object:
var objA:Object = new Object;
and then I pass it into an instance of a class:
var objB:Class = new B(objA);
and this is my destroy function inside of class B:
public function destroy():void
{
__objA = null // __objA being just objA
}
Does that destroy objA or does that just destroy a reference to the object inside of the instance of class B?

I don't believe objA will be destroyed. The reference itself ( __objA ) will be destroyed, but objA will continue to live on forever since the variable __objA merely points to objA.

objA and __objA are just references to an object created by "new Object". That object will not be destroyed as long as there is at least one reference to it still in existence.
For example, if objA is a local variable to a method, then as soon as the method finishes executing the objA reference no longer exists. Except of course if the method has any continuations (anonymous event listeners). If that's the case, objA will stay around until the listener is removed.

Related

Initialize a final variable with "this" in Dart

I have a class like this:
class A extends B {
final Property<bool> property = Property<bool>(this);
}
class Property<T> {
Property(this.b);
final B b;
}
But I get an error on this saying:
Invalid reference to 'this' expression.
I believe I can't access this at that moment, probably because the object reference is not ready yet.
So I tried other forms of initializing that variable like:
class A extends B {
final Property<bool> property;
A() : property = Property<bool>(this);
}
But I get the same error.
The only thing that works is:
class A extends B {
Property<bool> property;
A() {
property = Property<bool>(this);
}
}
Which needs me to remove the final variable declaration, which is something I don't want to.
How can I initialize a final variable in Dart that needs a reference to the object itself?
You can't reference this in any initializers as this hasn't yet been initialized itself, so you won't be able to set Property<bool> property to be final.
If you're just trying to prevent modification of the value of property from outside the instance, you can use a private member and provide a getter to prevent modification. Given your example, that would look something like this:
class A extends B {
// Since there's no property setter, we've effectively disallowed
// outside modification of property.
Property<bool> get property => _property;
Property<bool> _property;
A() {
property = Property<bool>(this);
}
}

Grails bind data to non-domain-class with type checking

I'm looking for a simple way to check some types in my params. If they exist they should have a certain type, if not they should have a default value. If they exist and their type is wrong, an exception should be thrown.
It would be nice to have the values in a handy container afterwards. Therefore I've tried passing params to the container's constructor and bindData on a container object. Neither is successful:
class ContainerClass {
Integer foo = 42;
}
class TestController {
def index(){
//doesn't throw, **even when params.foo = "2asdf3"**
ContainerClass meh = new ContainerClass();
bindData(meh, params);
println meh.foo //prints 42 when params.foo = "2asdf3"
// throws GroovyCastException: Cannot cast object '23' with class
// 'java.lang.String' to to class 'java.lang.Integer',
// **even when params.foo = "23"**
ContainerClass meh2 = new ContainerClass(params);
render "meh"
}
}
I'm using grails 3 if this is of importance.
You might use Command Objects to bind parameters to certain Data Type.
Reference : http://docs.grails.org/latest/guide/single.html?utm_content=bufferf77f5&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer#commandObjects
If you want to throw exceptions if certain data type does not match,that needs to be checked explicitly.

destroy displayObject from stage and garbage collector as3?

I need help with something very interesting. I try to remove child from parent or fro stage dinamicly but not just removeChild and I want to destroy entire object. Here is very simple example what I want to do.
public function TestProject()
{
holder = new Sprite();
this.addChild(holder);
object1 = new Sprite();
object1.name = "object1";
object1.graphics.beginFill(0x6daeff);
object1.graphics.drawRect(0,0,100,100);
holder.addChild(object1);
stage.addEventListener(MouseEvent.CLICK,onClick);
}
protected function onClick(event:MouseEvent):void
{
var tmp:DisplayObject = holder.removeChild(object1);
tmp = null;
// holder.removeChild(object1) = null; this give me error.
}
//with this code object1 was removed from stage but object1 is not null. When I debug
object1 = flash.display.Sprite ; etc.
I want to remove child and at the same this child to be null.
Any ideas...
To clean up memory you have to destroy all references to your object. In this case:
protected function onClick(event:MouseEvent):void
{
if (holder.contains(object1))
holder.removeChild(object1);
object1 = null;
}
or
protected function onClick(event:MouseEvent):void
{
if (object1.parent)
object1.parent.removeChild(object1);
object1 = null;
}
Note: When you'd applied null to local variable tmp you didn't affect the object1 instance variable.
Thanks for your answer but the point is in this example I write just one object. I Ask when I have 100 object for example. Something like this:
for(var i:int=0;i<holder.numOfChilder;i++)
{
holder.getChildAt(i).addEventListener(Event.MouseEvent,onObjectClick)
}
function onObjectClick():void
{
holder.removeChild(event.currentTarget as DisplayObject) = null;
}
child object are dynamic created and I want dynamic removed
To cleanup object that was created dynamically and to which you have no reference variable, just remove all event listers to it, to make it eligible for GC:
function onObjectClick(event:MouseEvent):void
{
var target:DisplayObject = (event.currentTarget as DisplayObject);
target.removeEventListener(MouseEvent.CLICK, onObjectClick);
holder.removeChild(target);
}
Note: there is no need to set null to you local variable cause it will die automatically since method run will be finished
Note2: u can set useWeakReference=true during adding your listener
to allow your listener being garbage-collected automatically.

Function stored as variable can cause reference cycle?

If I have a class, that stores an others class function as a variable, can that cause reference cycle?
For example
class ClassA {
var i = 0
func incrementI() {
i++
}
}
class ClassB {
private var function: () -> ()
init(function: () -> ()) {
self.function = function
}
func someFunc() {
function()
}
}
I cannot store in ClassB the variable function as weak or unowned, so can this cause reference cycle? Or this just reflects my poor understanding on reference cycles/function?
Reference cycles are exactly what they're name suggests. One object references another which references the original object. These can be made of two or more objects.
Why it's easy to make reference cycles using blocks or closures is because capturing self in a closure means the closure object has a reference to self. If self also has a reference to the closure than you have a reference cycle. I think your example is safe because you're passing the closure in ClassB's init which means that that closure shouldn't be able to have a reference to a non-existent object.
If your example took function as a method, then you'd have an issue as you could do this:
class ClassB {
...
func setSomeFunc(function : ()->()) {
self.function = function
}
func printSomething() {
print("Something")
}
}
...
func test() {
var x1 = {
print("Do Nothing")
}
var b : ClassB = ClassB(x1)
var x2 = {
b.printSomething()
}
b.setSomeFunc(x2)
}
In this example, we create x1 which has no external references.
[x1]
Then we create b with a reference to x1. This reference is added in ClassB's init.
[b]->[x1]
Then we create x2 with a reference to b. b is captured in the x2 closure which means that it will hold a strong reference to b.
[x2]->[b]->[x1]
We now assign a new function, x2, to b. This will break the reference from b to x1...
[x2]->[b]-x->[x1]
and replace it with a reference to x2.
[x2]->[b]-\ [x1]
/\ |
\-------/
As you can see, we now have a circular (or cyclical) reference. The only way to now break that reference is to set b's function member to reference something else, or to set x2's captured b value to something else.

class instance changed in callback method comparing to the main instance

in cpp:
void Character::jump(CCLayer *layer){
if (this->isAnimationPlaying) return;
up_or_down = UP;
body->runAction(CCSequence::actions(
CCMoveBy::actionWithDuration(0.5, ccp(0, 50)),
CCCallFuncND::actionWithTarget(body, callfuncND_selector(Character::upDownDone), this),
// CCCallFuncN::actionWithTarget(body, callfuncN_selector(Character::upDownDone)),
NULL));
this->isAnimationPlaying = true;
}
void Character::upDownDone(CCNode *node, CCObject *ob){
this->isAnimationPlaying = false; // *this is different from the this(class instance) in jump method, seems this in upDownDone is a new created instance*
}
So How can I get the class instance in a callback method? And can I make the this same for the main class instance and the callback's class instance?
EDIT:
Character is a class which has no parent class, and body is a member variable which is an instance of CCSprite.
Thanks.
because you are using body to call the function Character::upDownDone.
you should use this to call it.
CCCallFuncND* callFunc = CCCallFuncND::actionWithTarget(first_arg, secend_arg, third_arg);
body->runAction(callFunc);
assume your secend_arg is callfuncND_selector(Character::upDownDone)
then,
the first_arg is the caller, ie. the class instance who calls this function, in your code is body. but actually it should be this, or any instance of Charactor class
the CCNode* node (the first para that is been passed to your calling function) is the action runner, ie. body in your code. because you are using body->runAction()
the CCObject* obj (the second para that is been passed to your calling function) is a void pointer which is exactly the same with third_arg.
another way is use
void Character::upDownDone(CCNode *node, void *ob){
(Character*)ob->isAnimationPlaying = false;
}
Seems like you call the Character::upDownDone method using the instance "body" instead of this .May be you want this:
CCCallFuncND::actionWithTarget(this, callfuncND_selector(Character::upDownDone), body),

Resources