Interface function returning untyped value (*) while implementation return specific type? - actionscript-3

Out of curiosity I was wondering if it was possible to have an interface definition returning untyped values, while its implementations return typed value ?
For example, having the following interface :
interfaceExample
{
function someExampleFunction():*
}
implemented the following way :
classA implements interfaceExample
{
public function someExampleFunction():Int{ ... }
}
classB implements interfaceExample
{
public function someExampleFunction():String{ ... }
}
( I've googled with no result, maybe I haven't been able to ask the right way )
I guess the answer is 'no it's not possible in any way, Interface aren't designed like that' -- so what could be a friendly way to achieve such a thing ?

You're right, this won't compile. This is because the compiler doesn't support overloading of the signature of methods from parent classes or interfaces.
If you think about it, it doesn't really make sense to override the return type when implementing an interface because the code consuming your interface API should not depend on the implementation (int or String return value).
The solution to use really depends on what you are trying to do in the end. In general, the return type should be the common denominator between the different types you could produce. This could also be another interface that describes what to expect from the return value.

While I'm not heavily familiar with interface definitions, I do know that I write a lot of functions that work with typed and untyped arguments and returns.
In the event that what you're describing is not possible, and depending on what you're doing, I would recommend writing a simple function that can convert an untyped variable into a typed variable. They're fairly simple. Then, you could call this function to handle whatever data comes in via the interface definition.
A rough example (untested):
function convertDataTo(type:String, input:*):*
{
var rI:int;
var rN:Number;
var rS:String;
var rB:Boolean;
switch(type)
{
case "int":
if(isNaN(int(input))
{
rI = 0;
}
else
{
rI = int(input);
}
break;
case "Number":
if(isNaN(Number(input))
{
rN = 0;
}
else
{
rN = Number(input);
}
break;
case "Boolean":
if(input == "true")
{
rB = true;
}
else if(input == "false")
{
rB = false;
}
else
{
rB = Boolean(input);
}
return rB;
break;
case "String":
rS = input.toString();
break;
default:
trace("Invalid data type!");
return 0;
break;
}
}
You can also rewrite this function to convert from String type to any other type, and have your interface definition always return strings. On the other end, you can have a similar function that converts all variables to strings that can be interpreted by this function.
By the way, I've had to use that kind of string interpretation in writing my own scripting language for use inside one of my larger projects.
Of course, I don't pretend this answers your question directly, but I wanted to throw out this contingency in case what you're looking for doesn't work.

Related

Underscores in MvvmCross data binding

I'm using the fluent syntax and lambdas for data binding in MvvmCross. An example of this is:
var bindings = this.CreateBindingSet<MyTableCell, MyTableCellViewModel>();
bindings.Bind(titleLabel).To(vm => vm.MY_TITLE);
bindings.Apply();
Whenever I try this with an underscore in a view model property I get an exception:
Cirrious.CrossCore.Exceptions.MvxException: Unexpected character _ at
position 3 in targetProperty text MY_TITLE
I believe the error message is a result of MvvmCross parsing the data binding, yet this seems to only make sense for people using string-based data binding, not the lambda expression syntax.
Unfortunately, I cannot change the view models so I'm looking for a workaround to allow underscores in the view models. Any ideas?
I'd guess this is a general problem in the MvvmCross parser - probably in
private void ParsePropertyName()
{
var propertyText = new StringBuilder();
while (!IsComplete && char.IsLetterOrDigit(CurrentChar))
{
propertyText.Append(CurrentChar);
MoveNext();
}
var text = propertyText.ToString();
CurrentTokens.Add(new MvxPropertyNamePropertyToken(text));
}
In https://github.com/MvvmCross/MvvmCross/blob/v3/Cirrious/Cirrious.MvvmCross.Binding/Parse/PropertyPath/MvxSourcePropertyPathParser.cs#L80
Which probably needs to be fixed to something like:
while (!IsComplete &&
(char.IsLetterOrDigit(CurrentChar) || CurrentChar == '_')
There are workarounds you could do, but the easiest solution is probably to fix this and rebuild, rather than to try workarounds.
But if you do want to try workarounds....
Assuming this is static (non-changing) text and this is just a one-off for now, then one workaround might be to add a property to your cell called Hack and to then bind like:
bindings.Bind(this).For(v => v.Hack).To(vm => vm);
//...
private MyTableCellViewModel _hack;
public MyTableCellViewModel Hack
{
get { return _hack; }
set { _hack = value; if (_hack != null) titleLabel.Text = _hack.MY_VALUE; }
}
Another alternative (with the same assumptions) might be to use a value converter -
bindings.Bind(titleLabel).To(vm => vm.MY_TITLE).WithConversion(new WorkaroundConverter(), null);
// ...
public class WorkaroundConverter : MvxValueConverter<MyTableCellViewModel, string>
{
protected override string Convert(MyTableCellViewModel vm, /*...*/)
{
if (vm == null) return null;
return vm.MY_TITLE;
}
}

How to define the return type of AS3 method that may return or not return a result?

public function t()
{
if(xxx)return xxx;
//don't return anything
}
How to define the return type for such method?
A function either has to return nothing, or return something - it can't do both. The reason being, what if you write this code:
var someValue = someFunction();
How would this code be handled if sometimes someFunction returned a value, and sometimes it didn't?
Your problem is a really common one, though, and there are several ways to work around it.
Sentinel Values
You can return special-case values that you treat as non-values (such as null, NaN, "", or -1). These special-case values are called sentinel values. The users of your function (maybe your own code) would check the result after calling it. If it gets one of the sentinel values back, it doesn't use the result.
Try-style Functions
You could also use a pattern commonly used in C#/.Net that they call "Try-methods", but you can call "Try-functions". Actionscript doesn't work exactly like C#, but we can get close enough for this pattern to work.
To do this, return Boolean, returning true if you have a value, and false if you don't. Then give your function an Object parameter, and populate a property with the actual return value:
function trySomeFunction(result:Object) : Boolean
{
if(xxx)
{
result.Value = xxx;
return true;
}
return false;
}
// ...
var result:Object = { Value:null };
if(trySomeFunction(result))
{
// Do something with the value here
}
Exceptions
If your method failed to do what it promised to do, you can throw an exception. Then you don't have to worry about what gets returned, because your code just dies.
Exceptions are great because people who call your code don't have to learn as much. They don't have to know that your function only succeeded if it doesn't return some magic value that is different for every function, they don't need to check if your function returns true/false, and they don't need to know that some property gets populated on an object when the function succeeded.
Without exceptions, if they forget to check for your special value, or the result of a "Try-function", an error might happen further on in the program. Or it might not happen at all, and the program will continue running, but be broken. In these cases, it is much harder to track down the problem.
With exceptions, your code just blows up the second it detects a problem, and gives you the line of code where your program realized it couldn't work correctly.
If it is normal and okay for your function to fail, though, you probably shouldn't throw an exception. You should probably use a "Try-function" or a sentinel value instead.
Everything that Merlyn says is fine, though perhaps a bit of overkill. If your method needs the potential to return null, then just pass xxx back whether it's null or not...
public function t():MyReturnType
{
return xxx;
}
... since you're going to have to do check the special condition in the calling method anyway:
public function caller():void
{
var value:MyReturnType = t();
if (value)
doSomethingPositive();
else
copeWithNullState();
}
Some people think that this is wrong and advocate creating a special 'null value' object in your return class, like this:
public class MyReturnType
{
public static const NULL:MyReturnType = new MyReturnType(null);
public function MyReturnType(identifier:String)
...
}
then in your function either return an interesting MyReturnType or NULL:
public function t():MyReturnType
{
return xxx || MyReturnType.NULL;
}
but then you've not really improved your caller method so why bother?
public function caller():void
{
var value:MyReturnType = t();
if (value != MyReturnType.NULL)
doSomethingPositive();
else
copeWithNullState();
}
Whatever you choose to do, eventually you're just going to have to test for special cases in the caller method. Personally I'd say it's better to keep it as simple as possible, and the special 'null value' in your class is over-complication.
I write plenty of functions that might return an object reference, but may also return null, like this:
public function findThingById( id:int ):MyThingType
{
... code here to search for/load/lookup thing with matching id
if (found)
{
return thing;
}
return null;
}
Wherever you call a function that might return null, you would either test the return value for null explicitly, or if you expect null just don't do anything with the return value. For built-in data types, you would use a special value rather than null (like NaN for Numbers illustrated above), but the principle is the same.
public function t():type
{
if(xxx)return xxx;
//don't return anything
}
so something like:
private function derp():void{
}
private function derp2():int{
}
private function derp3():Boolean{
}
etc
its always good practice to define the return type, and return an indicator variable if false (i.e return -1 for number), but if its really necessary you can do this:
public function t()
{
if(xxx)return xxx;
//don't return anything
}
don't specify a return type at all, and either it will return xxx or undefined, but I highly encourage using a return type.
But since flash runs on virtual memory it can basically adapt to your return type so it makes it a little flexible so you can return what ever.
EDIT:
public function t()
{
if(true){
return xxx; //xxx can by of any type
}
return NaN
}
EDIT:
so lets say you want the condition with a return type of int you would have
public function t():int
{
if(true){
return xxx; //where xxx != -1
}
return -1
}
this when we get back any number other then negative 1 we know the condition was true, but if we get -1 the condition was false. But if you numbers are any real numbers, use NaN keyword:
public function t():Number
{
if(true){
return xxx; //where xxx != -1
}
return NaN
}
this way if you get NaN back it means your condition was false
I should also mention that when your dealing with NaN use the isNaN() to determine if the return type was NaN or not:
example:
if(isNaN(t()) == true){
//if condition in function t() was false;
}
There is no way a single function can return void as well as returning a type. This is because void is not part of any inheritance chain, it is a top level concept meaning something very specific; it doesn't return anything.
Don't get confused between null and void, undefined and void, NaN and void. They are different concepts.
The answer to your question is simply that it can't, nor should it be done. When you hit a problem like this, it's good practice to step back and ask 'why' do you need to do this.
I would highly encourage that you mark this question as closed, and instead posted a higher level problem. For example,
How would I structure a class that has a variable xxx that does this and that and will be eventually set to a number when the user clicks. But if the user never clicks, it will be unset.... ecetera ecetera....
If you are 100% convinced you should do something like you're asking, you could 'fake' it by
function f():* {
var xxx:Number = 999;
if(xxx) {
return xxx;
} else {
return undefined;
}
}
var xx:* = f();
trace(xx);
But remember, from that point onwards you will need to check everytime xx is used to see if it undefined. Otherwise it will lead to errors.

E4X in ActionScript

Looking at the E4X implementation in ActionScript, it occurs to me that they had to figure out how to do three things that I am not sure can be done within ActionScript regularly:
Properties/Getters prefixed with #:
var myAttribute = xmlPerson.#name;
Nameless functions for filtering:
xmlData.person.(/* predicate */)
lambda syntax for predicates:
xmlData.person.(#name == "Brian")
So here is my question: Are these just one-off capabilities (much like Vector.<>) they put in just for E4X, therefore keeping out of reach for us? Or do we, as ActionScript developers, have access to these features?
More specifically, I'd love to get access to the expression tree of that lambda predicate for my own code (not tied to the XML classes in any way).
I figured out that this is called the "filter operator"... but I am not sure how to harness it. Not sure I can... since ActionScript does not allow for operator overloading :(
As far as I know, it's not possible to harness the E4X syntax for other types of objects. It's really sad, because there's a lot of potential in it; especially the lamdba syntax.
I think what you need is the Proxy class. The mechanism of this class is quite interesting, allowing you to handle dynamic access to non-existent but algorithmically definable properties. In order to do this, you subclass the flash.utils.Proxy class.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/Proxy.html
The dynamic getter / setter logic is easy to implement. However attribute (#) access and the lambda syntax are tricky. Proxy getters do not see the # character for some reason and filter methods result in runtime errors. You can see them below:
package {
import flash.display.Sprite;
public class ProxyTest extends Sprite {
public function ProxyTest() {
var obj:ProxyObject = new ProxyObject();
trace(obj.testingDefault); // Invokes default logic.
trace(obj.#testingAttributes); // Invokes default logic. :(
trace(obj["(#testingLambda == 'testing')"]); // Invokes lambda logic.
trace(obj.filter("#testing == 'testing'")); // Just an idea
trace(obj.(#testing = "testing")); // Throws Error #1123: Filter operator not supported
}
}
}
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic class ProxyObject extends Proxy {
public function ProxyObject() {
}
override flash_proxy function callProperty(propName:*, ... args):* {
var name:String = propName.toString();
switch (name.charAt(0)) {
case '(':
trace("Lambda logic.");
break;
case '#':
trace("Attribute logic.");
break;
default:
trace("Default logic.");
break;
}
return "CALL: " + propName;
}
override flash_proxy function getProperty(propName:*):* {
var name:String = propName.toString();
switch (name.charAt(0)) {
case '(':
trace("Lambda logic.");
break;
case '#':
trace("Attribute logic.");
break;
default:
trace("Default logic.");
break;
}
return "GET: " + propName;
}
override flash_proxy function setProperty(propName:*, value:*):void {
}
}
I know I'm late, but Brain, it appears that filter operators ARE supported in AS3!!
Checkout this error I got:
TypeError: Error #1123: Filter operator not supported on type XYZ
On this line of code:
object.(getChildByName("image") as Sprite).addChild(img);
Well.. I suppose we figure out the rest ...

Why is it not possible to declare a function with VAR return type?

In C#, we have var data type but we can't use it as functions return type.
Why this is not possible?
public var myFunction()
{
var = some operations
}
I believe it's partly due to the design of the compiler. Eric Lippert blogged about why fields can't use implicit typing, and I suspect some of the same arguments hold for methods.
But you could easily end up with ambiguity anyway. For example:
var Method1(bool callMethod2)
{
return callMethod2 ? Method2() : null;
}
var Method2()
{
return Method1(false);
}
What should the type be here?
A simpler example:
var Method1(bool throwException)
{
if (!throwException)
{
return Method1(true);
}
throw new Exception("Bang!");
}
Admittedly this sort of ambiguity could simply be disallowed, but I suspect that the design team felt that the added complexity of both design and implementation wasn't worth the benefit. Don't forget that they're running with limited resources - given a choice between var for methods and async/await, I'd pick the latter in a heartbeat. (Admittedly there are other features I'd have picked instead of dynamic, but that's a different matter...)
Note that return type inference is performed for lambda expressions, so the very idea of it isn't crazy. For example:
IEnumerable<string> x = new[] { "x", "y", "z" };
var result = x.Select(s => { return s.Length; }); // Long form
There the compiler infers the complete type of the lambda expression when it performs overload resolution on Select, converting it to a Func<string, int>. It's not inconceivable to apply the same ideas to methods - just complicated.
var is NOT a datatype in C#. That's why you cannot use it as a return parameter. The compiler infers the type at compile time from the right handside of the assignment and bearing in mind that it is known at compile time you need to use the real type as return value. In C# 4.0 you could use the dynamic type:
public dynamic myFunction()
{
var = some operations
}

Finding out what type a certain interface is

I am creating a method that accepts a IOBJECT parameter. there is multiple class that implement this interface. I need to figure out which type IOBJECT is. how would i go about doing that
You can use typeof, instanceof, or the 'is' operator
It's not ideal, but you can use the "is" operator. Throw it into a switch of if else statment to figure things out.
if(obj is ClassA) {
//sweetness
} else if (obj is ClassB) {
//awesomeness
}
typeof will not work, as suggested in the other reply. It will likely return "object" in all cases. instanceof will work though.
You can do getQualifiedClassName() to get the class name of the object. You can also use describeType() which gives you a more complete description of all the methods and properties of the object.
There is information about both here:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/utils/package.html
It doesn't sound like an ideal situation though. You may want to do something where you can standardize the way you handle all items. For example:
public interface IObject {
function doSomething():void;
}
Then...
function myMethod(obj:IObject):void {
obj.doSomething();
}