-
-
Save effection/5276656 to your computer and use it in GitHub Desktop.
Better class macro in Sweet.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* class which allows 'private' (just non-enumerable prototype object) methods and variables | |
*/ | |
macro class { | |
case $className { constructor $constParam { $constBodyStatement... } public var {$public_vars ...} private var $private_vars $rest ... } => { | |
var $className = (function() { | |
function $className $constParam { | |
$public_vars ... Object.defineProperty(this, '_private_vars', { configurable: true, enumerable: false, value: $private_vars, writable: false}) | |
$constBodyStatement ... | |
} | |
Object.defineProperty($className.prototype, '_private_methods', { configurable: true, enumerable: false, value: {}, writable: false}) | |
//$className.prototype._private_methods = {}; | |
class $className { $rest ... } | |
return $className; | |
})(); | |
} | |
/** | |
* Empty constructor isn't allowed above so this allows public private declarations without constructor | |
*/ | |
case $className { public var ({$public_vars ...}) private var ($private_vars) $rest ... } => { | |
var $className = (function() { | |
function $className () { | |
$public_vars ... Object.defineProperty(this, '_private_vars', { configurable: true, enumerable: false, value: $private_vars, writable: false}) | |
} | |
Object.defineProperty($className.prototype, '_private_methods', { configurable: true, enumerable: false, value: {}, writable: false}) | |
class $className { $rest ... } | |
return $className; | |
})(); | |
} | |
/** | |
* Public instance method | |
* public myMethod() {} => class.prototype.myMethod() | |
*/ | |
case $className { public $methodName $methodParam $methodBody $rest ... } => { | |
$className.prototype.$methodName = function $methodParam $methodBody; | |
class $className { $rest ... } | |
} | |
/** | |
* Hidden method (aimed at being private/protected but accessible everywhere within the class and not defined in the constructor) | |
* function myMethod() {} => class.prototype._.myMethod() | |
*/ | |
case $className { function $methodName $methodParam $methodBody $rest ... } => { | |
$className.prototype._private_methods.$methodName = function $methodParam $methodBody; | |
class $className { $rest ... } | |
} | |
/** | |
* Public static method | |
* public static myMethod() {} => class.myMethod() | |
*/ | |
case $className { public static $methodName $methodParam $methodBody $rest ... } => { | |
$className.$methodName = function $methodParam $methodBody; | |
class $className { $rest ... } | |
} | |
/** | |
* Private (completely hidden to the outside world) static method | |
* private static myMethod() {} => function myMethod() | |
*/ | |
case $className { $(private static $pMethodName $pMethodParam $pMethodBody) ...} => { | |
$(function $pMethodName $pMethodParam $pMethodBody) ... | |
} | |
} | |
/** | |
* 'Private' variable access helpers | |
*/ | |
macro private { | |
/** | |
* 'Private' variable access var x = private(myVar); private(myVar) = x; private(myVar).a.b = null; private(myVar.a.b) = null; | |
*/ | |
case ($x) => { this._private_vars.$x } | |
/** | |
* 'Private' method calls private->myMethod(); | |
*/ | |
case .$x => { this._private_methods.$x } | |
/** | |
* 'Private' static method call/variable access. Optional but it makes the method type more clear at the call site private static.myMethod(); | |
*/ | |
case static.$x => { $x } | |
case (static).$x => { $x } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Person { | |
/** | |
* Declaring public & private variables must be directly under the constructor if there is one. Otherwise they can go anywhere | |
*/ | |
constructor(name) { | |
;//Can't have an empty constructor limitation if you don't need to use constructor params leave out the constructor declaration | |
} | |
public var { | |
this.name = name; | |
this.age = 0; | |
} | |
private var { | |
a: null, | |
b: name, | |
c: this.age | |
} | |
/** | |
* I have no access to the instance and am visible to the outside | |
*/ | |
public static create(name) { | |
return new Person(name); | |
} | |
/** | |
* I am just a prototype method. | |
*/ | |
public say(msg) { | |
console.log(this.name + " says: " + msg); | |
private(a) = new Person(this.name); | |
//Call a private method | |
private.myMethod(); | |
} | |
/** | |
* I am just a prototype method. | |
*/ | |
public other(foo) { | |
console.log("other method"); | |
} | |
/** | |
* I have access the same access as public but shouldn't be used outside of the class but in reality there are no restrictions. | |
* Other ways of defining privates in the constructor means prototype methods don't get access to private methods. | |
* I am actually just a prototype method in the non-enumerable prototype._private_methods | |
*/ | |
function myMethod() { | |
console.log('private'); | |
//Public access | |
console.log(this.name); | |
//Private access | |
private(a) = null; | |
//Private static access | |
print('Hello, World'); | |
//Also private static access | |
private static.print('Hello, World'); | |
private(static).print('Hello, World'); | |
} | |
/** | |
* I have no access to the instance but am not visible to the outside | |
*/ | |
private static print(msg) { console.log('private static: ' + msg); } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Person = function () { | |
function Person(name$2) { | |
this.name = name$2; | |
this.age = 0; | |
Object.defineProperty(this, '_private_vars', { | |
configurable: true, | |
enumerable: false, | |
value: { | |
a: null, | |
b: name$2, | |
c: this.age | |
}, | |
writable: false | |
}); | |
} | |
Object.defineProperty(Person.prototype, '_private_methods', { | |
configurable: true, | |
enumerable: false, | |
value: {}, | |
writable: false | |
}); | |
Person.create = function (name$5) { | |
return new Person(name$5); | |
}; | |
Person.prototype.say = function (msg$8) { | |
console.log(this.name + ' says: ' + msg$8); | |
this._private_vars.a = new Person(this.name); | |
this._private_methods.myMethod(); | |
}; | |
Person.prototype.other = function (foo$13) { | |
console.log('other method'); | |
}; | |
Person.prototype._private_methods.myMethod = function () { | |
console.log('private'); | |
console.log(this.name); | |
this._private_vars.a = null; | |
print('Hello, World'); | |
print('Hello, World'); | |
print('Hello, World'); | |
}; | |
function print(msg$21) { | |
console.log('private static: ' + msg$21); | |
} | |
return Person; | |
}(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment