Passing different class objects into a function and getting it's properties in Haxe? - haxe

Passing different class objects into a function and getting it's properties ?
For example:
I have two different class objects :
screenA = new ScreenA();
screenB = new ScreenB();
I pass the objects in the tween:
switch (state)
{
case States.SCREEN_A:
{
Actuate.tween(screenA, 0.6, {alpha: 1} ).ease(Sine.easeIn).autoVisible (true).onComplete(onComp, [screenA]);
}
case States.SCREEN_B:
{
Actuate.tween(screenB, 0.6, {alpha: 1} ).ease(Sine.easeIn).autoVisible (true).onComplete(onComp, [screenB]);
}
}
Now i want to access a method of the passed object here, when tween completes.
Tween is passing the object but i am unable to cast it in the function to get the object methods.
private function onComp(screen:?)
{
screen.load();
}
And compiler is always asking for the type. I have tried Dynamic / Any but then it says "load method not found", If i pass the object without any type arguments in the function then it is getting it as an object but not the class object.

There're a lot of ways you could do this, but one is with a common interface:
class ScreenA implements OnTweenComplete { ... }
class ScreenB implements OnTweenComplete { ... }
interface OnTweenComplete {
public function on_tween_complete();
}
Then your function is:
private function onComp(screen:OnTweenComplete)
{
screen.on_tween_complete();
}
Or perhaps, type-check it with Std.is and cast it:
private function onComp(screen:Dynamic)
{
if (Std.is(screen, OnTweenComplete)) {
(cast screen).on_tween_complete();
}
}

In this exact example, you can use load in the onComplete callback to simplify your code:
Actuate.tween (screenA, 0.6, { alpha: 1 }).ease (Sine.easeIn).onComplete (screenA.load);

Related

custom cast function and abstracts

This code outputs Null<_Test.Bar_Impl_>. I wanted it to output Foo but I see why it does not work that way. But may be I can somehow overcome this limitation.
My primary goal is to create function that will work like cast, but return null instead of throwing exception. And it should work with abstracts.
class Foo {
}
abstract Bar(Foo) {
}
class MyCast {
inline static public function doCast<T>(value: Any, type: Class<T>): Null<T> {
return Std.is(value, type) ? cast value : null;
}
}
class Test {
static function main() {
$type(MyCast.doCast(null, Bar));
}
}
Actually that cannot work at all like that, since Std.is(value, AbstractType) will always fail because the abstract does not exist any more at runtime.
See https://try.haxe.org/#1Afb5, and especially:
Use #:forward to access foo from Bar instances (forward doc)
Use from Foo to safe cast Foo instances into Bar instances (see implicit cast doc) (note that this feature on itself may be exactly what you were trying to achieve: https://try.haxe.org/#cc903)

Handle function calls on a class in Node.JS

Assuming that you have a class
class MyClass {
world() {
console.log("hello world");
}
}
I can run the method similar to the following:
var hello = new MyClass();
hello.world();
# outputs: hello world
Is there a way to handle direct function calls on an object? For example:
hello();
Returns: TypeError: hello is not a function.
Can I make this call a default function? For example, similar to PHP's invoke function ...
We can only make something callable in JavaScript if that thing is an object which, at some point, delegates to Function.prototype. Therefore, our class will need to extend Function or extend from a class which extends Function. We also need to be able to access instance variables from our class object (in order to call invoke()), so it needs to be bound to itself. This binding can only happen in the constructor.
Since our class will inherit from Function, we need to call super before being able to use this . However, the Function constructor actually takes a code string, which we won't have, because we want to be able to set invoke later on. So we'll need to extend Function in a different class which will be the parent class to our class and which will do the work of setting the prototype of our dummy function (which we need in order to be able to call the returned object). Bringing all of this together, we get:
class ExtensibleFunction extends Function {
constructor(f) {
// our link to Function is what makes this callable,
// however, we want to be able to access the methods from our class
// so we need to set the prototype to our class's prototype.
return Object.setPrototypeOf(f, new.target.prototype);
}
}
class MyClass extends ExtensibleFunction {
constructor() {
// we build an ExtensibleFunction which accesses
// the late-bound invoke method
super(function() { return this.invoke(); });
return this.bind(this); // and bind our instance
// so we have access to instance values.
}
invoke() {
console.log("Hello, world!");
}
}
x = new MyClass();
x(); //prints "Hello, world!"
I mostly adapted the techniques found in this answer in order to do this.
An interesting aspect of using this technique is that you could name MyClass something like Callable and remove the invoke method - then any class which extends Callable would become callable as long as it had an invoke() method. In fact...
class ExtensibleFunction extends Function {
constructor(f) {
// our link to Function is what makes this callable,
// however, we want to be able to access the methods from our class
// so we need to set the prototype to our class's prototype.
return Object.setPrototypeOf(f, new.target.prototype);
}
}
class Callable extends ExtensibleFunction {
constructor() {
// we build an ExtensibleFunction which accesses
// the late-bound invoke method
super(function() { return this.invoke(); });
return this.bind(this); // and bind our instance
// so we have access to instance values.
}
}
class CallableHello extends Callable {
invoke() {
console.log("Hello, world!");
}
}
class CallableBye extends Callable {
invoke() {
console.log("Goodbye cruel world!");
}
}
x = new CallableHello();
x(); //prints "Hello, world!"
y = new CallableBye();
y(); //prints "Goodbye cruel world!"
(Of course, you could get the same effect by setting properties on function objects, but this is more consistent I guess)

Overriding parent methods with contravariant arguments

Basically, I want to override a parent class with different arguments. For example:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
Then override that class, something like:
class HoldMore extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
set(value, value2);
}
override public function set(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
Obviously this will return an error, Field set overloads parent class with different or incomplete type. Is there a way around this? I tried using a public dynamic function, and then setting set in the new() function, but that gave a very similar error. Any thoughts?
This is just a complement to #stroncium's answer, which is totally correct.
Here is an example how it could look like:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
class HoldMore<T> extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
setBoth(value, value2);
}
// you cannot override "set" with a different signature
public function setBoth(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
alternatively, you could use an array as parameter or a dynamic object holding multiple values in order to "set" them using the same method, but you loose some of the compiler's type checking.
If you wrote the base class you could add an optional argument to it, this would be a workaround though, not directly what you want to do.
In the current state it totally won't work. There is not only 1 problem, but few of them:
Type T is meaningless in context of this new class, you should either use some concrete type or template this class over T.
You can not change the number of arguments of function when overriding it. However you can add another function(with a different name) to accept 2 arguments and do what you want (which is the way you would use in most languages, by the way).
I don't really understand how you see a contravariance problem there. The actual problem is that haxe doesn't support function overload. (It actually does, the function signature is name + full type, but that's not what you would want to write nor support, and is mostly used for js/java externs.)
Unfortunately the language doesn't allow it.

Calling Method of class within it

// What is the technical reason behind this scenarios..?
You're trying to use a statement other than a declaration directly inside the class - rather than within a method. When did you expect the method to get called?
Basically all you can have directly within a type is a bunch of declarations - methods, variables, constructors, events, nested types etc. Method calls (or any other statements) which aren't part of a declaration have to be written within methods, constructors etc.
Method call statement can not be part of a class declaration, but only within Function members declarations scope, such as Methods, Properties, Constructors etc.
For example:
public class ExampleClass
{
private void SayHelloWorld()
{
Console.Writeline("Hello World!");
}
public void CallSayHelloWorldMethod()
{
this.SayHelloWorld();
}
}
At the above example you can see that I call the SayHelloWorld method within the CallSayHelloWorldMethod metod.
Update:
The closest thing I can think of in your case is to use the class's constructor where your method call will be executed as soon as you'll instantiate your class:
public class ExampleClass
{
//The class constructor
public ExampleClass()
{
this.SayHelloWorld();
}
private void SayHelloWorld()
{
Console.Writeline("Hello World!");
}
}
And when you instantiating it, it will be immediately called:
//Your method call will be executed here
ExampleClass exampleClass = new ExampleClass();
You have a few problems... This won't even compile as you are trying to call the method obj.m1() in the class definition.
A obj = new A();
obj.m1(); // Why this code wont work??? --> This must be inside a method
When you create an instance of a class it will create a new member variable called obj which is an instance of A --> A obj = newA() above;
You will now be able to call obj's methods as in your second example.
Also, in order to get this to compile you will need to fix the m2 method:
public void m2() { //--> should have a curly brace
obj.m1(); // But This will work.
}

ViewHelper newable/injectable dilemma

I'm trying to design an application following Misko Heverys insights. It's an interesting experiment and a challenge. Currently I'm struggling with my ViewHelper implementation.
The ViewHelper decouples the model from the view. In my implementation it wraps the model and provides the API for the view to use. I'm using PHP, but I hope the implementation is readable for everyone:
class PostViewHelper {
private $postModel;
public function __construct(PostModel $postModel) {
$this->postModel = $postModel;
}
public function title() {
return $this->postModel->getTitle();
}
}
In my template (view) file this could be called like this:
<h1><?php echo $this->post->title(); ?></h1>
So far so good. The problem I have is when I want to attach a filter to the ViewHelpers. I want to have plugins that filter the output of the title() call. The method would become like this:
public function title() {
return $this->filter($this->postModel->getTitle());
}
I need to get observers in there, or an EventHandler, or whatever service (in what I see as a newable, so it needs to be passed in through the stack). How can I do this following the principles of Misko Hevery? I know how I can do this without it. I'm interested in how for I can take it and currently I don't see a solution. ViewHelper could be an injectable too, but then getting the model in there is the problem.
I didn't find the blog post you referenced very interesting or insightful.
What you are describing seems more like a Decorator than anything to do with dependency injection. Dependency injection is how you construct your object graphs, not their state once constructed.
That said, I'd suggest taking your Decorator pattern and running with it.
interface PostInterface
{
public function title();
}
class PostModel implements PostInterface
{
public function title()
{
return $this->title;
}
}
class PostViewHelper implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->post->title();
}
}
class PostFilter implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->post = $post;
}
public function title()
{
return $this->filter($this->post->title());
}
protected function filter($str)
{
return "FILTERED:$str";
}
}
You'd simply use whatever DI framework you have to build this object graph like so:
$post = new PostFilter(new PostViewHelper($model)));
I often use this approach when building complex nested objects.
One problem you might run into is defining "too many" functions in your PostInterface. It can be a pain to have to implement these in every decorator class. I take advantage of the PHP magic functions to get around this.
interface PostInterface
{
/**
* Minimal interface. This is the accessor
* for the unique ID of this Post.
*/
public function getId();
}
class SomeDecoratedPost implements PostInterface
{
public function __construct(PostInterface $post)
{
$this->_post = $post;
}
public function getId()
{
return $this->_post->getId();
}
/**
* The following magic functions proxy all
* calls back to the decorated Post
*/
public function __call($name, $arguments)
{
return call_user_func_array(array($this->_post, $name), $arguments);
}
public function __get($name)
{
return $this->_post->get($name);
}
public function __set($name, $value)
{
$this->_post->__set($name, $value);
}
public function __isset($name)
{
return $this->_post->__isset($name);
}
public function __unset($name)
{
$this->_post->__unset($name);
}
}
With this type of decorator in use, I can selectively override whatever method I need to provide the decorated functionality. Anything I don't override is passed back to the underlying object. Multiple decorations can occur all while maintaining the interface of the underlying object.

Resources