Testing the object type of a parameter passed into a actionscript function? - actionscript-3

How do you check if an Object passed into a function is the one you are expecting?
public function writeRecord(grid:IExtendedDataGrid, record:Object):String
{
ExternalInferface.call("alert","record " + record);
if (record.contains("HotListItem")
{
//# I have found my object
}
else
{
//# Wrong type of object
}
}
When I display my object to the ExternalInterface alert call it displays the following...
record [object HotListItem]
I would like to be able to test for this type of Object beforehand.

Using the is operator has resolved my question.
I tried the instanceof operator but this was flagged as deprecated.
Thanks to Organis
if (record is HotListItem)

Related

How to make a reference of or call a member function if that member function exists

I want to check that if a member function of a particular name exists on a object, if it does call the member function or make a reference of that member function.
Here I don't have type of the object, i.e. the object maybe does not implement any interface but has a member function cancel().
I used this method (reflection) to check if the member function exists, i.e. if (object::class.members.any { it.name == "cancel" }) and when this statement returns true I am sure that the method does exist but compiler is still unsure that the 'cancel' method exist in the object or not
fun canceller(object: Any): KFunction<Any>?
{
var canceller: KFunction<Any>? = null
// check if object has member function 'cancel'
if (object::class.members.any { it.name == "cancel" })
{
// make reference of that member function and return it
canceller = object::cancel //cancel is still not recognized as a member function and gives an error that "Unresolved reference: cancel"
// or just call it now
// object.cancel()
}
return canceller
}
I expect that canceller variable should be assigned to value.cancel(), but the compiler is unsure that cancel() function exist (with an error "Unresolved reference: cancel") in the object even after we supplied a check inside if statement
It's not meant to be used like this. Reflection is something you use if you don't know at compile time what you are dealing with at runtime. Some examples:
you need to use a type that's configured in some properties file (Class.forName("someTypeString").newInstance())
you have written an utility that extracts the contents of your object for debugging purposes
you need to access code that isn't really visible to you (private fields that you can't easily access, but you need to)
many more... but most of the time very special use-cases
Now what you have shown is a function reference (object::cancel). In order to use a function reference the compiler must know the type of object and the cancel-function must exist for that type. As object is of type Any and the if-condition is only relevant at runtime, the compiler does not know that there is a cancel-function available and therefore compilation fails.
Note that if you aren't doing anything special, you should rather check for a common type/interface. So for example, if your objects implement an interface Cancellable you could just change your code to something as follows:
fun canceller(object: Any): KFunction<Any>? {
var canceller: KFunction<Any>? = null
// check if object is of type Cancellable
if (object is Cancellable) {
// make reference of the Cancellable::cancel-function
canceller = object::cancel // smart-cast acting
// or you could also call it directly: object.cancel()
}
return canceller
}
or probably you could just spare that function altogether and end up with something like just:
val someObj : Cancellable = ...
// somewhere later:
someObj.cancel()
Reflection is rather expensive and if you aren't entirely sure what it is useful for, you should not use it.
If you really knew what you were doing... then ok... it's of course also possible to call that function via reflection and if you ask for the existance of a function via reflection you also have to call it via reflection:
object::class.members.first {
// note: I am using just the first function... if there are several, you need to check which one to use (parameter/type)
it.name == "cancel"
}
.call(object)
I think you can use reflections for this purpose.
myObject.javaClass.kotlin.members.any { it.name == "cancel" }
And the better way to express the idea of "object that has all the variables" is to define the interface and have all those object implemented
interface Achiever { val name: String }

AS3 Check if variable is String outputs MouseEvent info

UPDATE: I found a workaround using different code. I am leaving this question in cause someone wants to answer why this was happening and maybe it can help someone else as well. Thanks
I am trying to check if a variable is a string, in this case if it has a url in the string. But the code is executing and in the trace statement I get this:
if (theWebsite is String)
trace(theWebsite);
output:
[MouseEvent type="click" bubbles=true cancelable=false eventPhase=3 localX=2259.8671875 localY=2485.85205078125 stageX=1003.25 stageY=71 relatedObject=null ctrlKey=false altKey=false shiftKey=false buttonDown=false delta=0 commandKey=false controlKey=false clickCount=0]
MainStage? [object Main_Activate] and website? [MouseEvent type="click" bubbles=true cancelable=false eventPhase=3 localX=2259.8671875 localY=2485.85205078125 stageX=1003.25 stageY=71 relatedObject=null ctrlKey=false altKey=false shiftKey=false buttonDown=false delta=0 commandKey=false controlKey=false clickCount=0]
Here is the code that creates this variable.
1.
MenuScreen.One_btn.addEventListener(MouseEvent.CLICK, webViewButton("http://www.MyWebsite.com"));
2.
public function webViewButton(theWebsite:String):Function {
trace("made it here: " + theWebsite); /// output: www.MyWebsite.com
return function(e:MouseEvent):void {
trace("made it here too: " + theWebsite); //output: www.MyWebsite.com
removeMenuScreen(theWebsite);
}
}
3.
public function removeMenuScreen(theWebsite:String = null, e: Event = null) {
if (theWebsite is String) {
trace("But did I make it here? " + theWebsite);
// OUTPUTS all the above code mentioned earlier.
}
I am using that function for other things as well so that is why its set up that way. HOW can I fix this to have that code execute only if it is a defined string? Thanks for any tips.
The code you posted does not produce the output you posted.
What would produce the "[MouseEvent ...]" output is if you had something like addEventListener(MouseEvent.CLICK, removeMenuScreen). Why? Because a MouseEvent will get coerced to its string value since the removeMenuScreen handler's first parameter theWebsite is of type String.
So, to answer your question: it already is only being executed when theWebsite is a string. And it will only ever be a string, or null, otherwhise if coercion to a string is not possible it will throw a runtime error.
If you want to avoid runtime coercion, make the parameter untyped:
public function removeMenuScreen(theWebsite:* = null) {
if (theWebsite is String) {
trace("But did I make it here? " + theWebsite);
} else if (theWebsite is MouseEvent) {
trace("Or did I make it here?", theWebsite)
}
}
I don't recommend you go down this path, though, because it adds a lot of unclarity, which leads to bugs and hard debugging.

Can I safely pass null to Function.apply in place of thisArg argument?

To make public API of SWF more reliable, I usually wrap callbacks in closure with try/catch block:
private function addCallback(functionName:String, closure:Function):void {
ExternalInterface.addCallback(functionName, wrapEventHandler(closure));
}
private function wrapEventHandler(closure:Function):Function {
var self:Main = this;
return function(...arguments):* {
try {
return closure.apply(self, arguments);
} catch (error:Error) {
// Print error report here
}
}
}
When exception occurs in 'closure', error report will be printed.
I noticed that it works fine even when using 'null' instead of 'self':
closure.apply(null, arguments);
Is it safe to use 'null' in this case?
Callback I register with ExternalInterface aren't static functions; they use Main's class fields.
It works just fine with null, NaN and self. I couldn't find any problems with using NaN/null.
Passing the this argument to apply() is optional, and the parameter default value is NaN.
Parameters
thisArg:* (default = NaN) — The object to which the function is
applied.
Likewise with, call():
You can pass the value null for the thisObject parameter to invoke a
function as a regular function and not as a method of an object.
For example, the following function invocations are equivalent:
Math.sin(Math.PI / 4)
Math.sin.call(null, Math.PI / 4)

Generic way to get reference to a method's caller?

I have 2 classes representing 2 objects. From the "whoCalledMe" function, I want to find out what object called the function (without passing that information in as an argument). I've used a make-believe property, "caller", that would give me the reference I'm looking for. Is there a generic way I can get a reference to the caller from there?
package {
public class ObjectCallingTheFunction {
public var IDENTITY:String = "I'm the calling function!";
public function ObjectCallingTheFunction() {
var objectWithFunction:ObjectWithFunction = new ObjectWithFunction();
objectWithFunction.whoCalledMe();
}
}
}
package {
public class ObjectWithFunction {
public function whoCalledMe ():void {
trace(caller.IDENTITY); // Outputs: "I'm the calling function!"
}
}
}
It would help to know why you need this, because I have a feeling that you don't really. If the method is anonymous, you can bind the 'this' keyword by using .apply on the method:
var foo:Function = function(arg:int):void
{
trace(this);
};
var bar:Object = {
toString: function():String { return "bar"; }
};
var baz:Object = {
toString: function():String { return "baz"; }
};
foo.apply(bar); // <-- Prints "bar"
foo.apply(baz); // <-- Prints "baz"
If the method is an instance method method however, it's a bound method and thus "this" will always point to the instance of the class it's declared in, no matter if you redefine it by using the apply method. If it's a static method, "this" doesn't make sense and the compiler will catch it.
Other than that, there's really no way short of declaring it as a parameter. There used to be a caller property on the arguments object, but it was deprecated when AS3 was released. You can get a reference to the function itself through arguments.callee, but that's not really what you asked for.
In AS3 you can throw an error and then parse the Stack Trace to find out detailed informations.
You can check here for an example:
http://www.actionscript-flash-guru.com/blog/18-parse-file-package-function-name-from-stack-trace-in-actionscript-as3
If you want to find the called function's name you can follow this example:
http://www.flashontherocks.com/2010/03/12/getting-function-name-in-actionscript-3/
I guess you want to know the caller in debug purpose. if so I would recommend setting a breakpoint in the method/function instead of tracing. When the code breaks you can backtrace the caller and a lot more. Works in Flash IDE as well as Flashbuilder. Google "as3 breakpoints" if you are new to breakpoints.
Here is the official Adobe article on using arguments.callee
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/arguments.html
It includes sample code.
Hope this helps.

ActionScript - Receiving Name of Calling Function or Constructor?

long shot: is it possible to get the name of a calling function or the constructor from the called function? is it possible to determine the previous function of the thread?
i would like to call some setter functions from my constructor and have my setter functions determine if it was the constructor that called them.
currently, i'm setting a boolean for this functionality, but perhaps there is another way?
public function Constructor(myNumber:Number)
{
this.myNumber = myNumber;
}
public function set myNumber(value:Number):void
{
myNumberProperty = value;
//if constructor called this, return;
//else do some other stuff;
}
Quote from liveDocs:
Unlike previous versions of ActionScript, ActionScript 3.0 has no arguments.caller property. To get a reference to the function that called the current function, you must pass a reference to that function as an argument. An example of this technique can be found in the example for arguments.callee.
It was in AS2.0... It unfortunately throws an error if done in AS3.0.
Technically, you should be able to do this by generating an error and getting its stack trace. The constructor will have to be on that stack trace.
try
{
throw new Error();
}
catch (e:Error)
{
// parse this for the constructor name
trace(e.getStackTrace());
}
That would be for detecting where a function call came from...
I would still go for your solution (setting the flag), as it's more oop and probably far faster in terms of performance.