OOP - How to call a class method internally in Reason - oop

I have a testFactory class. The purpose is to be able to pass in a factory, and then console out results for demoing purposes. As of now, when trying to call createProductA within the test method , the compiler will complain that createProductA is unbound (Unbound value createProductA).
What is the proper syntax for calling a method internally in a class?
class testFactory (factory: abstractFactory) => {
as _;
pub createProductA => factory#createProductA;
pub createProductB => factory#createProductB;
pub test () => {
Js.log createProductA;
Js.log createProductB;
}
};

This is where the as _; part of the class definition comes in, if you've ever wondered what that was for.
createProductA and createProductB are methods, not functions, so they need to be called on an object. Reason/OCaml won't automatically bind the current object to a name like this or self, but puts it on you to do it, which is precisely what as does, and _ means, as usual, "I don't care about this". So if you change as _; to e.g. as self; you'll be able to reference self as the current object elsewhere.
Try this:
class testFactory (factory: abstractFactory) => {
as self;
pub createProductA => factory#createProductA;
pub createProductB => factory#createProductB;
pub test () => {
Js.log self#createProductA;
Js.log self#createProductB;
}
};

Related

OOP - How to create an instance of one type called to another type in Reason

I have two abstract products types:
type abstractProductA = {.
methodA: string
};
type abstractProductB = {.
methodB: int
};
Used to create the following product classes:
class productA1 = {
pub methodA => "This is methodA of ProductA1";
};
class productB1 = {
pub methodB => 1;
};
I would like to call the instance of abstractProductA, as well as abstractProductB in my abstract factory. Something like the following(syntax is off, I know):
type abstractFactory = {.
createProductA: abstractProductA,
createProductB: abstractProductB
};
So that when I create new concreteFactory using the following class:
class concreteFactory1 = {
pub createProductA => (new productA1);
pub createProductB => (new productA1);
};
and constructer:
let g = new concreteFactory1#createProductB;
Js.log (g#methodA);
the compiler should complain that createProductB only takes an int, and not an string(which it currently does not).
Thank you, and any suggestions are more than welcome.
It seems the error should occur where createProductB returns productA1 instead of productB1. In order to achieve that, you'll need to define a virtual class for abstractFactory instead of just an object type, and then have concreteFactory explicitly inherit from it.
class virtual abstractFactory = {
pub virtual createProductA: abstractProductA;
pub virtual createProductB: abstractProductB;
};
class concreteFactory1 = {
inherit abstractFactory;
pub createProductA => (new productB1);
pub createProductB => (new productB1);
};
This will produce the following error on pub createProductA => (new productB1):
This expression has type productB1 but an expression was expected of type abstractProductA The second object type has no method methodB
See the full example here

OOP - How to create a constructor in Reason

Let's say I have two concrete factories:
class concreteFactory1 = {
inherit abstractFactory;
pub createProductA => (new productA1);
pub createProductB => (new productB1);
};
class concreteFactory2 = {
inherit abstractFactory;
pub createProductA => (new productA2);
pub createProductB => (new productB2);
};
I then would like to have another class that calls factory method(e.g. concreteFactory1#createProductA), based on factory passed into class. Something like the following (syntax is wrong, I know):
class testFactory factory => {
as _;
pub createProductA => Js.log factory#createProductA;
};
Any suggestions are more than welcome. Thank you.

OOP - How to create an interface in Reason

Let's say I have the following abstractProductA class with a public method called methodA :
class abstractProductA = {
pub methodA => "name";
};
I would like to create an interface that says function methodA should always return a string. Something similar to
interface abstractProductA {
abstractProductA(): string
}
only in reason, and then have class implement it. Any suggestions are more than welcome. Thank you
What you're really asking for it seems is how to define and use an abstract class, which is called a virtual class in OCaml/Reason:
class virtual virtualProductA = {
pub virtual methodA: string;
};
class abstractProductA = {
inherit virtualProductA;
pub methodA = "name";
};
An interface is more for consumers to abstract away an implementation, and while a virtual class can be used as an interface by itself, since OCaml/Reason objects are structurally typed you can also just specify the object type you need. And of course you can bind it to a name if you like:
type interfaceA = {.
methodA : string
};
let f (p: interfaceA) => Js.log p#methodA;
f (new abstractProductA);

How to set lifetime for boxed closure capturing `self`?

I want to return an iterator (in particular, a Filter). I used a previous answer that suggests returning a boxed iterator. The problem is that my filter captures self and I get:
error: closure may outlive the current function, but it borrows self, which is owned by the current function
But I think I'm being explicit that self has lifetime 'a and so does the Box I'm returning:
fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> {
Box::new( (0..32).filter( |&pos| match self.at(pos) { Occupied::Empty => false, _ => true } ) )
}
This is an attempt to simplify my first effort, where I created a new FooIterator which owns a reference to self in basically the same way.
If I use most of the same syntax to simply capture self as a member reference it works fine:
struct Foo { junk: i32 }
struct FooIterator<'a> { foo: &'a Foo }
impl Foo {
fn foo<'a>(&'a self) -> Box<FooIterator<'a>> {
Box::new( FooIterator { foo: self } )
}
}
You get an error because your closure receives a reference to self, which itself is a reference. However, since the reference points to a local variable, that reference becomes invalid as soon as the function returns.
To fix this, add the move keyword before the closure. This instructs the compiler to move the closed-over variables in the closure, rather than pass a reference to those variables to the closure.
fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> {
Box::new( (0..32).filter(move |&pos| match self.at(pos) { Occupied::Empty => false, _ => true } ) )
}

How to store HashMap and its Values iterator in the same struct? [duplicate]

I currently want to define a struct for a Piston game using GamerIterator:
pub struct MyGame<'a> {
game_window: GameWindowGLFW,
game_iter: GameIterator<'a, GameWindowGLFW>,
//...
}
The GameIterator is generic in the GameWindow and its lifetime. I want to tell the compiler that it has the same lifetime as the field "game_window"/"the whole struct" and leave out the lifetime for the struct.
I also have difficulties initializing this:
MyGame {
game_window: GameWindowGLFW::new(GameWindowSettings {/*...*/},
game_iter: GameIterator::new(&mut game_window, &game_iter_settings), // game_window cannot be used here
//...
}
I think that I can work around the initialization issue by using Option<GameIterator<...>> and an init() method, but I would like to avoid this because I can guarantee that game_iter is present after new() finishes.
What is the idiomatic way to write this?
Not only is there an issue with initialization, there could also be issues with destruction, if GameIterator implemented Drop: the compiler would have to know that it needs to destruct game_iter before game_window, otherwise game_window would have a reference to a destroyed GameWindowGLFW while running its drop() method.
There's no way to pass the lifetime of the struct itself as a lifetime argument. The only thing you can do is remove the game_window field from MyGame and pass a GameWindowGLFW instance to MyGame's initializer. If you want to encapsulate this so that the user doesn't need to create a GameWindowGLFW, you could write a method that creates a GameWindowGLFW and a MyGame on the stack and calls a closure that accepts a MyGame argument only.
pub struct MyGame<'a> {
game_iter: GameIterator<'a, GameWindowGLFW>,
//...
}
impl<'a> MyGame<'a> {
fn new(game_window: &'a mut GameWindowGLFW) -> MyGame<'a> {
MyGame {
game_iter: GameIterator { game_window: game_window },
}
}
}
fn start_game(callback: |game: &mut MyGame|) {
let mut game_window = GameWindowGLFW;
let mut game = MyGame::new(&mut game_window);
callback(&mut game);
}
fn main() {
start_game(|game| {
/* use game here */
});
}