Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I think I just completed my own challenge. I've added a second (optional) argument to the CLASS declaration macro for the superclass of the class being declared.</p> <p>My original implementation created a lot of inline junk around the constructor, so I decided to wrap some convenience functions up in a macro helper object to avoid redundancy.</p> <p>Here are the current incarnations of my class-like OOP macros:</p> <pre><code>// class-like oo #ifndef BASE #define BASE $$_ #endif #define COLLAPSE(code) code #define NAMESPACE(ns) var ns=BASE._ns(this).ns=new function() #define CLASS(c,__ARGS...) var c=[BASE._class(this),[__ARGS][0]]; \ new function() #define CTOR(c) BASE._extend($$_##c,c[1],this); \ c=c[0].c=$$_##c; function $$_##c #define PUBLIC(fn) BASE._public(this).fn=fn;function fn #define PRIVATE(fn) function fn #define STATIC(fn) BASE._static(this).fn=fn;function fn // macro helper object COLLAPSE(var BASE=new function(){ function Clone(){}; function clone (obj) { Clone.prototype=obj; return new Clone; }; function merge (sub, sup) { for (var p in sup) if (sup.hasOwnProperty(p)) sub[p]=sup[p]; }; this._extend = function (sub, sup, decl) { if (sup) { merge(sub, sup); sub.prototype=clone(sup.prototype); sub.prototype.constructor=sub; }; if (decl) { merge(sub.prototype, decl); decl._static=sub; decl._public=sub.prototype; }; }; this._static=this._ns=this._class=function (obj) { return (obj._static || obj); }; this._public=function (obj) { return (obj._public || obj); }; }) </code></pre> <p>... here's a test namespace ...</p> <pre><code>//#include "macros.js" NAMESPACE (Store) { CLASS (Cashier) { var nextId = 1000; this.fullName = "floater"; CTOR (Cashier) (fullName) { if (fullName) this.fullName = fullName; this.id = ++nextId; this.transactions = 0; } PUBLIC (sell) (item, customer) { this.transactions += 1; customer.inventory.push(item); } STATIC (hire) (count) { var newCashiers = []; for (var i=count; i--;) { newCashiers.push(new Cashier()); } return newCashiers; } } // Customer extends Cashier, just so we can test inheritance CLASS (Customer, Cashier) { CTOR (Customer) (name) { this.name = name; this.inventory = []; this.transactions = 0; } PUBLIC (buy) (item, cashier) { cashier.sell(this, item); } CLASS (Cart) { CTOR (Cart) (customer) { this.customer = customer; this.items = []; } } } } </code></pre> <p>... and here's the output ...</p> <pre><code>var $$_=new function(){ function Clone(){}; function clone (obj) { Clone.prototype=obj; return new Clone; }; function merge (sub, sup) { for (var p in sup) if (sup.hasOwnProperty(p)) sub[p]=sup[p]; }; this._extend = function (sub, sup, decl) { if (sup) { merge(sub, sup); sub.prototype=clone(sup.prototype); sub.prototype.constructor=sub; }; if (decl) { merge(sub.prototype, decl); decl._static=sub; decl._public=sub.prototype; }; }; this._static=this._ns=this._class=function (obj) { return (obj._static || obj); }; this._public=function (obj) { return (obj._public || obj); }; } var Store=$$_._ns(this).Store=new function() { var Cashier=[$$_._class(this),[][0]]; new function() { var nextId = 1000; this.fullName = "floater"; $$_._extend($$_Cashier,Cashier[1],this); Cashier=Cashier[0].Cashier=$$_Cashier; function $$_Cashier (fullName) { if (fullName) this.fullName = fullName; this.id = ++nextId; this.transactions = 0; } $$_._public(this).sell=sell;function sell (item, customer) { this.transactions += 1; customer.inventory.push(item); } $$_._static(this).hire=hire;function hire (count) { var newCashiers = []; for (var i=count; i--;) { newCashiers.push(new Cashier()); } return newCashiers; } } var Customer=[$$_._class(this),[Cashier][0]]; new function() { $$_._extend($$_Customer,Customer[1],this); Customer=Customer[0].Customer=$$_Customer; function $$_Customer (name) { this.name = name; this.inventory = []; this.transactions = 0; } $$_._public(this).buy=buy;function buy (item, cashier) { cashier.sell(this, item); } var Cart=[$$_._class(this),[][0]]; new function() { $$_._extend($$_Cart,Cart[1],this); Cart=Cart[0].Cart=$$_Cart; function $$_Cart (customer) { this.customer = customer; this.items = []; } } } } </code></pre> <p>Inheritance, internal classes, and nested namespaces seem to work fine. What do you think, is this a useful approach to class-like OOP and code reuse in js? Let me know if I've missed anything.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload