📄 classfactory.js
字号:
/*
* Isomorphic SmartClient
* Version 6.5 (2008-04-30)
* Copyright(c) 1998-2007 Isomorphic Software, Inc. All rights reserved.
* "SmartClient" is a trademark of Isomorphic Software, Inc.
*
* licensing@smartclient.com
*
* http://smartclient.com/license
*/
//> @object ClassFactory//// Sets up a real inheritance structure for Javascript objects.// We separate out class objects from prototypes, so each gets its own inheritance chain. // This allows us to set up superclass calls, maintain class vs. instance variables and more!//// The ClassFactory is a singleton object that holds the miscellaneous pieces of our inheritance// mechanism.//// Your main interaction with the ClassFactory is to create new classes:// <code>ClassFactory.defineClass("MyClass", "mySuperClass");</code>//// @see class:Class//// @visibility external// @treeLocation Client Reference/System//<//// create the ClassFactory singleton object//// isc.addGlobal("ClassFactory", {}); //>DEBUG// give it a class name so that methods added to it get labelledisc.ClassFactory.Class = "ClassFactory"; //<DEBUG // ClassFactory defines the notion of an "Instance", "ClassObject" and an "Interface". Add methods// to isA for recognizing these objects.isc.addMethods(isc.isA, { //> @classMethod isA.Instance() // // Is <code>object</code> an instance of some class? // // @param object (object) object to test // @return (boolean) true == <code>object</code> is an instance of some class // @visibility external //< Instance : function (object) { return (object != null && object._prototype != null)}, //> @classMethod isA.ClassObject() // // Is <code>object</code> a class object? // // @param object (object) object to test // @return (boolean) true == <code>object</code> is a Class Object // @visibility external //< ClassObject : function (object) { return (object != null && object._isClassObject == true)}, //> @classMethod isA.Interface() // // Is <code>object</code> an interface object? // // @param object (object) object to test // @return (boolean) true == <code>object</code> is a Interface Object // @visibility external //< Interface : function (object) { return (object != null && object._isInterface == true)}, InstancePrototype : function (object) { return (isc.isAn.Instance(object) && object._prototype == object) }});//// add methods to the ClassFactory//isc.addMethods(isc.ClassFactory, { //> @classMethod ClassFactory.defineClass() // // Create a new class, which can then be used to create instances of this object type. // <P> // The new Class is returned by <code>defineClass</code>, is available as // <code>isc.<i>ClassName</i></code> and is also available in global scope if not in // +link{class:isc,portal mode}. // <P> // Also creates a new function <code>+link{isA,class:isA}.<i>ClassName()</i></code> object // for identifying instances of this Class. // // @param className (string) Name for the new class. // @param [superClass] (Class) Optional SuperClass Class object or name // @return (Class) Returns the new Class object. // // @visibility external //< // Internal notes: // Every ClassObject has: // { // Class : [string classname], // _isClassObject : true, // _instancePrototype : [instance prototype for class], // // _superClass : [pointer to superClass ClassObject (if this class is not a root class)] // // _subClassConstructor : [constructor function that creates subclass ClassObjects] // } // // Every InstancePrototype (and Instance) has: // { // Class : [string classname] // _instanceConstructor : [constructor function that creates instances] // _classObject : [ClassObject for this class] // _prototype : [the instance prototype (this same object)] // } defineClass : function (className, superClass, interfaces, suppressSimpleNames) { return this._defineNonRootClass(className, superClass, interfaces, null, suppressSimpleNames); }, //> @classMethod ClassFactory.defineInterface() // // An "Interface" is an API definition plus a skeletal implementation of that API. // // Interfaces are "mixed in" to another class in order to allow the target class to "support" // the interface. Interfaces typically require the target class to provide one or two core // methods, and then the interface itself provides the many convenience methods and method // variations that can be written in terms of the core methods. // // For example, a List interface could require only get(index) and getLength() from the target // class, and could provide getRange(), indexOf() and other standard List operations. If the // target class has a more efficient way of supporting getRange() than the generic // implementation in the List interface, the target class can directly implement getRange(), // and the target class' version of getRange() takes precedence. // // Comparison to other languages: // - in Java, an "interface" is just an API definition, with no implementation. The SmartClient // notion of interfaces is closer to an "abstract class", except that in Java you can only // inherit from one abstract class, whereas in SmartClient you can mixin as many Interfaces // as you want. Also, in SmartClient an Interface can contain both instance and class (aka // "static") methods. // - in Ruby, a Mix-in module corresponds exactly to the SmartClient Interface concept. // // Writing Interfaces: // - If you are writing an interface and want to indicate that a method must be implemented in // the target class in order for your interface to work, use addMethods to add a method with // the special value ClassFactory.TARGET_IMPLEMENTS. If the target class does not // implement the method and it gets called, an error will be logged. // - you can subclass an interface to create another interface, but you can't use Super to // call superclass methods within the interface inheritance chain // - interfaces have no constructor ("init"), so they cannot set up initial state other than by // setting up class or instance properties // - if you declare a method in an interface, and mix the interface into a class, you can't // call Super() and get the interface method -- the one you place in your instance will // override the one from the interface. // // To make this work, you have to create an intermediate class, then subclass that. Eg: // // CF.defineInterface("face1"); // face1.addMethods({ foo:function() {} }); // // CF.defineClass("class1"); // CF.mixInInterface("class1", "face1"); // // class1.addMethods({ // foo : function () { // // NOTE: a Super() call here will NOT go to the face1.foo method // } // }) // // CF.defineClass("class2", "class1"); // class2.addMethods({ // foo : function () { // // NOTE: a Super() call WOULD go to the face1.foo method // // (assuming class1.foo was not present) // } // }) // //< defineInterface : function (className, superClass) { return this._defineNonRootClass(className, superClass, null, true); }, //> @classMethod ClassFactory.defineRootClass() // // Variant of defineClass for creating a root class (a class with no superclass). // // @param className (string) Name for the new class //< defineRootClass : function (className) { return this._defineClass(className, null); }, //> @classMethod ClassFactory._defineNonRootClass() // // Define a class or interface which is assumed not to be a root class, that is, either the // superclass must be valid or there must be a valid ClassFactory.defaultSuperClass. //< _defineNonRootClass : function (className, superClass, interfaces, asInterface, suppressSimpleNames) { // if no superClass was specified, use the default rootClass superClass = (superClass || isc.ClassFactory.defaultSuperClass); // if we didn't find a superClass, something went wrong -- bail if (!superClass) { //>DEBUG isc.Log.logWarn("isc.ClassFactory.defineClass(" + className + ") called with null" + " superClass and no ClassFactory.defaultRootClass is defined."); //<DEBUG return null; } return this._defineClass(className, superClass, interfaces, asInterface, suppressSimpleNames); }, //> @classMethod ClassFactory._defineClass() // // Internal method to actually create a class or interface. <code>superclass</code> must // already be valid. //< _$iscPrefix : "isc.", _$Window : "Window", _$Selection : "Selection", _classTimes : {}, _defineClass : function (className, superClass, interfaces, asInterface, suppressSimpleNames) { // If we have an ID collision, warn the user and clobber the existing object var ignoreGlobalOverride = (isc.Browser.isMoz && (className == this._$Window || className == this._$Selection)); var existingObject, inISCSpace, useSimpleNames = (isc._useSimpleNames && !suppressSimpleNames); existingObject = isc[className]; if (existingObject != null) inISCSpace = true else if (useSimpleNames && !ignoreGlobalOverride) { existingObject = window[className]; } if (existingObject != null && className != "IButton" ) { var errorString = "New Class ID: '" + className + "' collides with ID of existing " + // NOTE: this check is required in case there is a collision on // window.Class. At that moment, isc.isA.Class is not a // function, but the String "isA" (isc.isA && isc.isA.Function(isc.isA.Class) && isc.isA.Class(existingObject) ? "Class object '" : "object with value '") + existingObject + "'. Existing object will be replaced."; if (!inISCSpace) errorString += "\nThis conflict would be avoided by disabling " + "ISC Simple Names mode. See documentation for " + "further information." // Note: If the Log class hasn't loaded yet, we don't warn about this collision. // This should be ok in almost every case as Log loads early during the smartClient // libs, but if this proves to be an issue, we could hang onto the error string and // wait until after Log has loaded to log a warning. if (window.isc.Log) isc.Log.logWarn(errorString);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -