Author: johnh
Date: Fri Feb 25 00:25:15 2011
New Revision: 1074362
URL: http://svn.apache.org/viewvc?rev=1074362&view=rev
Log:
CLosure-style Object Orientation.
A small helper library, currently unused, facilitating this form of JS
programming in inheritance situations.
Added:
shindig/trunk/features/src/main/javascript/features/cloo/
shindig/trunk/features/src/main/javascript/features/cloo/cloo.js
shindig/trunk/features/src/main/javascript/features/cloo/feature.xml
Added: shindig/trunk/features/src/main/javascript/features/cloo/cloo.js
URL:
http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/cloo/cloo.js?rev=1074362&view=auto
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/cloo/cloo.js (added)
+++ shindig/trunk/features/src/main/javascript/features/cloo/cloo.js Fri Feb 25
00:25:15 2011
@@ -0,0 +1,160 @@
+// Copyright 2011, Google Inc.
+
+/**
+ * Get a cloo!
+ *
+ * Simple utils for CLosure-style Object Orientation.
+ * JavaScript inheritance via prototype is a little awkward and too permissive.
+ * Method overrides are actually method overwrites, and importantly there's
+ * no such thing as private state: all properties attached to "this" are public
+ * and accessible.
+ *
+ * With this library, object-oriented JS APIs are implemented as function
+ * closures with private internal variables. Exported APIs are returned from
+ * these as Objects themselves.
+ *
+ * To define a class, simply define a Function that returns an Object whose
+ * keys define the class's external API, with that Object wrapped as:
+ * cloo.obj(opt_classname, super1, super2, ..., exported);
+ *
+ * To define an interface/abstract method in your exports, use cloo.interfc():
+ * cloo.obj({ foo: cloo.interfc() });
+ *
+ * Exported symbols that begin with an underbar are *not* inherited.
+ *
+ * Consequences of this mechanism are:
+ * + "True" private variables and functions are supported, by declaring them
+ * in the class's Function body without exporting them.
+ * + Quasi-"protected" methods are supported by defining a base class exporting
+ * methods whose name begins with an underbar.
+ * + A form of multiple inheritance is implicitly supported, by providing
+ * multiple superclass objects to the cloo.obj() function. Override
precedence
+ * is that last-superclass-wins. In practice, this should only be used with
+ * superclasses that don't have state, ie. comprise only of interface
methods.
+ * This is not programmatically enforced by the library to keep code lean.
+ * + Base-class state must be accessed via getters and setters, which may be
+ * "protected" as described above.
+ *
+ * Meaningless example exhibiting all features:
+ * var MyBase = (function(config, params) {
+ * var self = cloo.me();
+ * var handler = function() { };
+ * var cfg = config;
+ * var color = params["color"] || "red";
+ *
+ * function setColor(newColor) {
+ * color = newColor;
+ * }
+ *
+ * function callHandler() {
+ * handler(self());
+ * }
+ *
+ * return cloo.obj({
+ * setColor: setColor,
+ * _getColor: function() { return color; },
+ * getHeight: cloo.interfc() // Makes MyBase implicitly abstract
+ * });
+ * });
+ *
+ * var MyClass = (function(config, params) {
+ * var super = MyBase(config, params);
+ * var height = params["height"] || 34;
+ *
+ * function getHeight() {
+ * // Blue objects are always 123 in height.
+ * return super._getColor() === "blue" ? 123 : height;
+ * }
+ *
+ * return cloo.obj(super, {
+ * getHeight: getHeight
+ * });
+ * }
+ *
+ * var myClassInstance = MyClass({}, { height: 12, color: "red"});
+ */
+
+window['cloo'] = (function() {
+ var UNKNOWN_NAME = "(n/a)";
+ var selfs = [];
+
+ function InterfaceMethod(className, methodName) {
+ return function() {
+ throw "Class " + className + " missing " + methodName + "()";
+ }
+ }
+
+ var INTERFACE_PLACEHOLDER = InterfaceMethod(UNKNOWN_NAME, UNKNOWN_NAME);
+
+ function interfaceCreator() {
+ return INTERFACE_PLACEHOLDER;
+ }
+
+ function hasOwnFunctionProperty(obj, key) {
+ return obj.hasOwnProperty(key) && typeof obj[key] === "function";
+ }
+
+ function objectCreator() {
+ var args = arguments;
+ var className = UNKNOWN_NAME;
+ var ix = 0;
+ if (typeof args[0] === "string") {
+ className = args[0];
+ ix = 1;
+ }
+
+ // Create return Object.
+ var out = {};
+
+ for (; ix < (args.length - 1); ++ix) {
+ var parent = args[ix];
+ // Copy keys over from parent that aren't intended
+ // to be "protected" ie starting with an underbar.
+ for (var key in parent) {
+ if (hasOwnFunctionProperty(parent, key) && !/^_/.test(key)) {
+ out[key] = parent[key];
+ }
+ }
+ }
+
+ // Then override with new exports, replacing
+ // interface placeholders with properly-named versions.
+ var exports = args[ix];
+ for (var key in exports) {
+ if (hasOwnFunctionProperty(exports, key)) {
+ if (exports[key] === INTERFACE_PLACEHOLDER) {
+ exports[key] = InterfaceMethod(className, key);
+ }
+ out[key] = exports[key];
+ }
+ }
+
+ var lastIx = selfs.length-1;
+ if (lastIx >= 0 && !selfs[lastIx]) {
+ selfs[lastIx] = out;
+ }
+
+ return out;
+ }
+
+ function selfStorage() {
+ var ix = selfs.length;
+ if (ix && !selfs[ix-1]) {
+ throw "me() must be followed by obj()";
+ }
+ selfs.push(null);
+ return function() {
+ var obj = selfs[ix];
+ if (!obj) {
+ throw "me() access before obj creation";
+ }
+ return obj;
+ };
+ }
+
+ return {
+ interfc: interfaceCreator,
+ obj: objectCreator,
+ me: selfStorage
+ };
+})();
Added: shindig/trunk/features/src/main/javascript/features/cloo/feature.xml
URL:
http://svn.apache.org/viewvc/shindig/trunk/features/src/main/javascript/features/cloo/feature.xml?rev=1074362&view=auto
==============================================================================
--- shindig/trunk/features/src/main/javascript/features/cloo/feature.xml (added)
+++ shindig/trunk/features/src/main/javascript/features/cloo/feature.xml Fri
Feb 25 00:25:15 2011
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations under the License.
+-->
+<feature>
+ <name>cloo</name>
+ <gadget>
+ <api>
+ <exports type="js">cloo</exports>
+ </api>
+ <script src="cloo.js"/>
+ </gadget>
+ <container>
+ <api>
+ <exports type="js">cloo</exports>
+ </api>
+ <script src="cloo.js"/>
+ </container>
+</feature>