What's the difference between Item and Class<Item> - haxe

Assuming we have
class Item {}
What's the difference between Item and Class<Item>?
Actually, what Class<Item> means and how it's supposed to be used?

You have some explanation of this in the Haxe manual.
Item is the type of the instances of the class in the code block you have posted. Class<Item> is the type of the class itself. It is a bit confusing, but is a common concept present in other OO languages like Java, too.
The utility of Class<Item> is to query in runtime for the methods or fields in a class. This is usually called reflection, and is useful in many particular contexts like metaprogramming, dependency injection or ORM, among others. There is a page in the Haxe manual dedicated to reflection, too.

After some playing I came to something like this example to understand.
class Main {
static function main()
{
var item = createItem(Item);
var item2 = createItem(Item2);
var dupItem = duplicateItem(item);
var dupItem2 = duplicateItem(item2);
}
static function duplicateItem(item:Item):Item
{
trace('Duplicate ' + item);
var itemType = Type.getClass(item);
var item:Item = Type.createInstance(itemType,[]);
return item;
}
static function createItem(itemType:Class<Item>):Item
{
trace('Create ' + itemType);
var item:Item = Type.createInstance(itemType,[]);
return item;
}
}
class Item
{
public function new ()
{
trace("Item 1");
}
}
class Item2 extends Item
{
public function new ()
{
super();
trace("Item 2");
}
}
Output:
Main.hx:23: Create [class Item]
Main.hx:34: Item 1
Main.hx:23: Create [class Item2]
Main.hx:34: Item 1
Main.hx:44: Item 2
Main.hx:14: Duplicate [object Item]
Main.hx:34: Item 1
Main.hx:14: Duplicate [object Item2]
Main.hx:34: Item 1
Main.hx:44: Item 2

Related

How to use class functions in another class?

How can i use class instance in another class like a pointer in C++ to class instance functions?
Example:
class A {
constructor()
{
this.block = [];
}
method()
{
return this.blocks.length;
}
}
another class:
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method(); // here i'm getting cannot get length of undefined
}
}
If i'm trying to to like that i'm getting problems to call it
You can try this. Here, when creating B class's instance I give into it an A class's instance as argument. Then inside B we can call A instance's methods, and access its properties.
Also, as #ViaTech posted you can use static methods to access them without needing to initialize an object of the class. That is what static methods is. Refer Static Methods
class B {
constructor(instance)
{
this.instance = instance;
}
method()
{
this.instance.method();
}
}
class A {
constructor()
{
}
method()
{
console.log("A's method");
}
}
var a = new A();
var b = new B(a);
b.method(); // A's method
You can easily do this in JS by calling a static method like so:
class A {
static write(){ //static method
console.log("Called write from A");
}
}
class B {
doIt(){
A.write();
}
}
let b = new B();
b.doIt();
Option 2, you instantiate the class in the constructor of the other like so:
class A {
write(){
console.log("Non-static write() called from class A");
}
}
class B {
constructor() {
this.a = new A();
}
doIt(){
this.a.write();
}
}
let b = new B();
b.doIt();
There are a few ways:
I accidentally switched between PHP and Javascript, but the principles are the same for both)
Use static functions:
Normally, you have a this in the class. Say you have this code:
class Car {
let color;
public function setColor(newColor){ this.color = newColor;}
}
let car = new Car();
car->setColor('green')`
The setColor function's this refers to that car. You can make let anotherCar = new Car(), then when you do anotherCar->setColor('red') you only change that car, not the first one. Simplistic: You can create multiple instances.
If you do not need that, but need the class once, you can make it static. A simple way to explain would be "you have a collection of seperate functions, just put into a wrapping class (which doesn't do a lot really)". For instance, you might have some sanatizing methods:
class Sanitize {
static function makeHtmlSave(input){
return doYourMagicHere(input);
}
static function removeXssCode(input){
return doMoreMagicHere(input);
}
}
This way, you can reuse it multiple times. If you want to use it, you do Sanitize::makeHtmlSave(someCode) where you need it. There isn't a Sanitize thing, it's just a wrapper to access the frunctions inside it.
Use extend:
You can extend a class. Say you have a generic class Vehicle, which has some properties (eg a motor, numberWeels, color) and you can extend that with more specific classes:
class Vehicle {
let color;
public function setColor(newColor){ this.color = newColor}
}
class Car extends Vehicle {
let hasAirco = false;
public function hasAirco(newValue){ this.hasAirco = newValue};
}
If you do let car = new Car(), you get a Car object, that extends/enlarges/complements the Vehicle class, so you can use both its (public) functions. Internally, Car can use the functions of Vehicle too.
Just pass it
class One {
// some stuff
}
class Two{
let otherObject;
construct(givenObject){
this.otherObject = givenObject;
}
}
You can now do this let a = new One(); let b = new Two(a);. You can not use the functions of One inside Two, but you can still use a->doSomething(). This solution feels like the easiest, but it almost never is. Classes/objects are tricky stuff, but I've rarely uses this solutions. There are use cases, but often it's a bad smell indicator.

Can I overload method in module.export in node.js?

I have an app.js with this code:
var addnote = (title,body) => { /* enter code here */ }
module.exports = {addnote};
Can I add another addnotes function with different parameters to that file?
Function overloading in JavaScript does not exist like in other programming languages such as C# and Java.
What you should be looking to do is pass an object as a parameter that has properties attached and filter them out there..
You could call different functions from your little 'mapping function' just implement the logic there if it isn't big (to keep the code clear).
function foo(parameters){
var title = parameters.title;
var body = parameters.body;
if(parameters.extraProperty){
// oh we have extraProperty passed in too, run a different function?
bar(title, body, parameters.extraProperty); // ??
}
}
foo({title: 'Title', body: 'Body', extraProperty: 'This is extra...'});
If this is your own custom module, you can use the concept of function overriding, where each child class can have its own way to handle something and also have a default way to do things.
class Parent {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello ${this.name}`);
}
}
class Child1 extends Parent {
constructor(name) {
super(name);
}
greet() {
console.log(`Hey there ${this.name}. This is Child 1`);
}
}
class Child2 extends Parent {
constructor(name) {
super(name);
}
greet() {
console.log(`Hi there ${this.name}. This is Child 2`);
}
}
const o1 = new Child1('Foo')
const o2 = new Child2('Foo')
o1.greet();
o2.greet();
But if you are trying to override a function in an external module(You do not have access to that code, like a library), my suggestion is to create a wrapper and add functionality there.

Work with external array

I would like to write a method that will returns an object and puts it to external array,but array index should be increase after a method was fulfilled.
On next time, when I call method once againe,an object should wrote to neighboring cell in external array.Can you advice me any ideas or show me any examples?Thank you.
If I have correctly understood you question, you should use List<T> type for your "external array". It has Add(T item) method that allows you to add items exactly the same way as you've described. Let's say your object is of type Foo:
public void Test()
{
var externalArray = new List<Foo>();
var foo1 = MyMethod(externalArray);
var foo2 = MyMethod(externalArray);
}
public Foo MyMethod(List<Foo> list)
{
var item = new Foo();
list.Add(item);
return item;
}

Putting static functions in a Haxe typedef

In the programming language Haxe, I have multiple different 'item' classes that should be able to give a value when provided with some arguments. These functions should have no contact with actual object instances, but still belong in these class, thus, they should be static.
However, I want to be able to pass in the 'Apple' or 'Mango' class (not an instance) and call a static method. Normally I would create a typedef if I wanted to be able to access method, however what do I do when the method is static?
eg -
class food
+eat()
+throw()
Apple extends food
+eat()
+(static) getFatLevels (p:Person)
Mango extends food
+eat()
+throw()
+(static) getFatLevels (p:Person)
...
function chooseBestFood () {
for (food in Foods){
if (food.getFatLevels(person) < lowest){
return (food);
}
}
}
Typedefs work fine, but you need to use class notation to avoid "is method but should be var" errors:
typedef HasMagic = {
function magic():Void;
}
class Foo {
public static function magic()
{
return 314;
}
}
class Bar {
public static function magic()
{
return 42;
}
}
class Test {
static function main()
{
var items:Array<HasMagic> = [Foo, Bar];
for (i in items)
trace(i.magic());
}
}
(on try haxe)
You might also need to restrict DCE in some cases.
I don't follow how you would use typedefs here. However, if you know your child classes will all implement this static method, you can do the following in a non-type-safe way:
class Food
{
static function main() {
var myFoodClass:Class<Food> = Apple;
var method = Reflect.field(myFoodClass, "getFatLevels");
trace(Reflect.callMethod(myFoodClass, method, []));
}
}
class Apple extends Food
{
public static function getFatLevels():Int
{
return 5;
}
}

Retrieving an Enum through a class and its descendants

I have a class that I've defined, and I have a number of child classes derived from it. The parent class has an enum (let's call it 'Barf'). Each descendant ALSO has an enum with the same name but not the same values. What I'm trying to figure out how to do is write a method in the ancestor class that gets the version of Barf for the actual class of the instantiated object. So if I create an instance of Ancestor, I'd like to have this method process the entries for Ancestor.Barf . If I create an instance of one of the child classes of Ancestor, I'd like to have the method process Childx.Barf values.
Obviously this is going to be a Reflection solution, but my reflection skills are pretty sparse. Any help?
Just for the fun of it, here is a possible approach:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
public void ProcessValues() {
var type = GetType();
var nestedEnums = from t in type.GetNestedTypes()
where t.IsEnum
select t;
var nestedEnum = nestedEnums.Single();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
}
// The following prints:
// Drinking Jolt
// Drinking RedBull
Ancestor x = new Descendant();
x.ProcessValues();
Of course, you could achieve the same thing using polymorphism:
public class Ancestor {
public enum Caffeine {
Tea,
Coffee
}
protected virtual Type GetNestedEnum() {
return typeof(Ancestor.Caffeine);
}
public void ProcessValues() {
var nestedEnum = GetNestedEnum();
foreach(var val in Enum.GetValues(nestedEnum)) {
Console.WriteLine("Drinking {0}", val);
}
}
}
public class Descendant : Ancestor {
public new enum Caffeine {
Jolt,
RedBull
}
protected override Type GetNestedEnum() {
return typeof(Descendant.Caffeine);
}
}
As Justin Morgan has pointed out however, having the need for such a construct may be an indication of an underlying design issue in your code.

Resources