1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/method/Readme.md Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,117 @@ 1.4 +# method 1.5 + 1.6 +[](http://travis-ci.org/Gozala/method) 1.7 + 1.8 +Library provides an API for defining polymorphic methods that dispatch on the 1.9 +first argument type. This provides a powerful way for decouple abstraction 1.10 +interface definition from an actual implementation per type, without risks 1.11 +of interference with other libraries. 1.12 + 1.13 +### Motivation 1.14 + 1.15 + - Provide a high-performance, dynamic polymorphism construct as an 1.16 + alternative to existing object methods that does not provides any 1.17 + mechanics for guarding against name conflicts. 1.18 + - Allow independent extension of types, and implementations of methods 1.19 + on types, by different parties. 1.20 + 1.21 +## Install 1.22 + 1.23 + npm install method 1.24 + 1.25 +## Use 1.26 + 1.27 +```js 1.28 +var method = require("method") 1.29 + 1.30 +// Define `isWatchable` method that can be implemented for any type. 1.31 +var isWatchable = method("isWatchable") 1.32 + 1.33 +// If you call it on any object it will 1.34 +// throw as nothing implements that method yet. 1.35 +//isWatchable({}) // => Exception: method is not implemented 1.36 + 1.37 +// If you define private method on `Object.prototype` 1.38 +// all objects will inherit it. 1.39 +Object.prototype[isWatchable] = function() { 1.40 + return false; 1.41 +} 1.42 + 1.43 +isWatchable({}) // => false 1.44 + 1.45 + 1.46 +// Although `isWatchable` property above will be enumerable and there for 1.47 +// may damage some assumbtions made by other libraries. There for it"s 1.48 +// recomended to use built-in helpers methods that will define extension 1.49 +// without breaking assumbtions made by other libraries: 1.50 + 1.51 +isWatchable.define(Object, function() { return false }) 1.52 + 1.53 + 1.54 +// There are primitive types in JS that won"t inherit methods from Object: 1.55 +isWatchable(null) // => Exception: method is not implemented 1.56 + 1.57 +// One could either implement methods for such types: 1.58 +isWatchable.define(null, function() { return false }) 1.59 +isWatchable.define(undefined, function() { return false }) 1.60 + 1.61 +// Or simply define default implementation: 1.62 +isWatchable.define(function() { return false }) 1.63 + 1.64 +// Alternatively default implementation may be provided at creation: 1.65 +isWatchable = method(function() { return false }) 1.66 + 1.67 +// Method dispatches on an first argument type. That allows us to create 1.68 +// new types with an alternative implementations: 1.69 +function Watchable() {} 1.70 +isWatchable.define(Watchable, function() { return true }) 1.71 + 1.72 +// This will make all `Watchable` instances watchable! 1.73 +isWatchable(new Watchable()) // => true 1.74 + 1.75 +// Arbitrary objects can also be extended to implement given method. For example 1.76 +// any object can simply made watchable: 1.77 +function watchable(object) { 1.78 + return isWatchable.implement(objct, function() { return true }) 1.79 +} 1.80 + 1.81 +isWatchable(watchable({})) // => true 1.82 + 1.83 +// Full protocols can be defined with such methods: 1.84 +var observers = "observers@" + module.filename 1.85 +var watchers = method("watchers") 1.86 +var watch = method("watch") 1.87 +var unwatch = method("unwatch") 1.88 + 1.89 +watchers.define(Watchable, function(target) { 1.90 + return target[observers] || (target[observers] = []) 1.91 +}) 1.92 + 1.93 +watch.define(Watchable, function(target, watcher) { 1.94 + var observers = watchers(target) 1.95 + if (observers.indexOf(watcher) < 0) observers.push(watcher) 1.96 + return target 1.97 +}) 1.98 +unwatch.define(Watchable, function(target, watcher) { 1.99 + var observers = watchers(target) 1.100 + var index = observers.indexOf(watcher) 1.101 + if (observers.indexOf(watcher) >= 0) observers.unshift(watcher) 1.102 + return target 1.103 +}) 1.104 + 1.105 +// Define type Port that inherits form Watchable 1.106 + 1.107 +function Port() {} 1.108 +Port.prototype = Object.create(Watchable.prototype) 1.109 + 1.110 +var emit = method("emit") 1.111 +emit.define(Port, function(port, message) { 1.112 + watchers(port).slice().forEach(function(watcher) { 1.113 + watcher(message) 1.114 + }) 1.115 +}) 1.116 + 1.117 +var p = new Port() 1.118 +watch(p, console.log) 1.119 +emit(p, "hello world") // => info: "hello world" 1.120 +```