========================================================== ==========================================================
Qomolangma openproject V1.0
Category: rich Web Client
Key words: JS Oop, JS framwork, rich Web Client, Ria, Web component,
Dom, dthml, CSS, JavaScript, JScript
Project Initiation: aimingoo (aim@263.net)
Project Team: aimingoo, Leon (pfzhou@gmail.com)
Contributor: Jingyu (zjy@cnpack.org)
========================================================== ==========================================================
I. Complete OOP support in Qomolangma: object. js
~~~~~~~~~~~~~~~~~~
Qomo has provided object. js since field test4. This unit is used to support Complete OOP features in qomo. Pass
Javascript in object. js and qomo has changed from prototype inheritance to class inheritance ". And
The change is almost completely transparent to developers.
Through object. JS, qomo supports the following object-oriented features:
-Attribute and reader (getter/setter)
-Class Registration and class inheritance, and registration of classes in namespaces
-(Inherited) method call of the parent class (inherited)
(Todo: in Safari, object. js in qomo is not supported because the function. Caller attribute is not supported)
Ii. Oop syntax in Qomolangma
~~~~~~~~~~~~~~~~~~
Qomo indeed extends some JS syntax. However, unlike some other js oop implementation solutions: qomo is based on JS syntax
Instead of adding some replacement identifiers/keywords. The latter implementation scheme may require a separate
Syntax translation system/interpretation engine. But qomo is not required, and basically, because syntax parse does not exist,
Therefore, qomo runs faster, and the code written by the developer is exactly the same as the code in the debugger.
Qomo provides three global functions described in the form of keywords: Class (), attribute () and abstract ().
Class and abstract actually use the class and abstract keywords retained by Js. This means that in the future
(For example, in qomo for JS 2.0) qomo may delete them.
Among these functions, class () is used to register a constructor function to a class; attribute () is used to quickly declare
And initialization features; abstract () is used to declare an abstract method.
Qomo provides three global functions that can only be used during class registration and initialization: _ set (), _ Get (), and _ Cls ().
They start with "_", indicating that the context for calling them is restricted: they can only be called during the class declaration process.
In object. JS, the object () class is also rewritten. The rewritten object () and the original JavaScript Object () have
Identical features. In fact, its prototype is an example of the original JavaScript Object.
Rewrite object () instead of directly using the original one because there is an important convention in qomo:
-Qomo should allow the free use of the "{}" syntax to declare a Direct Volume object, and this object must not have any
What is the "visible" attribute.
Since qomo uses the class inheritance system, qomo registers a global base class: tobject.
1. Class declaration and Class Registration)
----------
The method for declaring a class in qomo is exactly the same as the method for declaring an "object constructor (function)" in standard Js.
However, after declaring a class, qomo needs to call class () to register it. For example:
----------
// Class declaration
Function myobject (){
This. value = 'hello, qomoer !!! ';
}
// Class Registration
Tmyobject = Class (tobject, 'myobject ');
// Create an instance and call
VaR OBJ = new myobject ();
Alert (obj. value );
----------
We also noticed that, apart from registering multiple classes, other (basic) syntaxes of qomo are no different from those of standard Js.
However, if you use class () registration, the object instance OBJ will have the following three "redundant" method calls:
-Obj. Get (): obtains the feature value.
-Obj. Set (): Set the feature value.
-Obj. inherited (): inherits (CALLS) the parent class method.
For the features of qomo classes and object instances, see Example: testcase/baseobjectdemo.html
Next we will introduce some syntaxes related to these three methods.
2. Use of features
----------
In Delphi, attributes can contain readers, and can be used in C # and other advanced languages. Including in js2.0
The attribute reader declaration syntax is also provided. However, these are all based on properties.
Qomo cannot provide an "extended Syntax" to enable JS 1.3 to support "attribute reader ". Therefore, qomo borrowed
The word "attribute" in C # realizes the attribute that can be customized for the reader. In fact, as C # recommends
Similarly, attribute is "the most innovative structure ".
In qomo, you can directly declare features in "class declaration" (note that these feature declarations/methods do not appear in the attributes of the object instance ).
, Even if you use the for .. in operation), you do not need to describe it in advance:
----------
Function myobject (){
This. getvalue = function (){
Return 100;
}
}
Tmyobject = Class (tobject, 'myobject ');
VaR OBJ = new myobject ();
Alert (obj. Get ('value '));
----------
In short, qomo considers all methods starting with 'get/set' as a "Reader Method" with a specified feature ".
Therefore, a simple line of "this. getvalue = function () {...}" has the following semantics:
-Declare a feature named "value" (inside the object instance)
-Its read method (getter) is getvalue ()
-Its write method (setter) will directly operate on the "value" feature itself
In the above example, we can see that getvalue () will return 100 directly. Then how can we return
What is the value of the value feature? -- Because setter is not declared, this internal value is operated directly. See this example:
----------
Function myobject (){
This. getvalue = function (){
Return this. Get ();
}
}
Tmyobject = Class (tobject, 'myobject ');
VaR OBJ = new myobject ();
OBJ. Set ('value', 1000 );
Alert (obj. Get ('value '));
----------
This example shows that "(only) inside the reader function" can be called without the "name" parameter:
-This. Get (): used to retrieve internal feature data
-This. Set (): used to set the value of internal feature data
Note that these two calls always occur inside the reader method, and this always points to the current instance. In addition
Method. For example:
----------
Function myobject (){
This. setvalue = function (v ){
Return this. Set (V * 2 );
}
}
Tmyobject = Class (tobject, 'myobject ');
VaR OBJ = new myobject ();
OBJ. Set ('value', 1000)
Alert (obj. Get ('value '));
----------
In terms of internal implementation, qomo adopts the "Write replication" technology, so the initial values of all instances of a class are
Is the same. However, if an instance is overwritten, the instance has a different value. In addition, subclass object instances
It also shares a reference (instead of a copy) of the parent class features ). However, when an Instance tries to write a feature value, it will write it in its own number
Data Partition, without affecting the class or other instances.
The initial value of a feature is declared by the attribute () function. It can only be called during the class declaration stage. For example:
----------
Function myobject (){
Attribute (this, 'value', 100, 'rw ');
}
Tmyobject = Class (tobject, 'myobject ');
VaR OBJ = new myobject ();
Alert (obj. Get ('value '));
----------
Attribute () parameters are described as follows:
-1. Base: Must be this
-2. Name: Specifies the feature name. It must start with an uppercase letter.
-3. Value: Initial Value
-4. Tag: flag character. Currently, it is only used to describe the read/write features. It includes characters: R, W
Attribute () Tag parameter (currently) is used to describe read/write. If you try to read a write-only feature
An exception, and vice versa. However, there is no such restriction within the reader method. For example:
----------
Function myobject (){
Attribute (this, 'value', 100, 'R ');
This. getvalue = function (){
This. Set (100 );
Return this. Get ();
}
}
Tmyobject = Class (tobject, 'myobject ');
VaR OBJ = new myobject ();
Alert (obj. Get ('value '));
// The following code will cause an exception
// Obj. Set ('value', 'Hi, Error! ');
----------
However, the tag declared by attribute () is not mandatory. That is to say, even if the read-only/write feature is declared,
You can still invalidate "Read-Only/write" by specifying the name of the reader. For example:
----------
Function myobject (){
Attribute (this, 'value', 100, 'R ');
This. setvalue = function (v ){
This. Set (v );
}
}
Tmyobject = Class (tobject, 'myobject ');
VaR OBJ = new myobject ();
OBJ. Set ('value', 'Hi, success! ');
Alert (obj. Get ('value '));
----------
The reason for this design is that the subclass has the opportunity to rewrite the Reader Method of the features of the parent class. -- They are just names
But the read/write performance is not necessarily the same. For example:
----------
Function myobject (){
Attribute (this, 'value', 100, 'R ');
}
Tmyobject = Class (tobject, 'myobject ');
Function myobjectex (){
This. setvalue = function (v ){
This. Set ('value is: '+ V );
}
}
Tmyobjectex = Class (tmyobject, 'myobjectex ');
VaR OBJ = new myobjectex ();
Alert (obj. Get ('value'); // display the property values inherited from myobject ().
OBJ. Set ('value', 'Hi, success! '); // Set a new value for instance features
Alert (obj. Get ('value'); // display the new value
VaR obj2 = new myobject ();
Alert (obj2.get ('value'); // Detection: Other instances are not affected.
// For myobject (), the value attribute cannot be written, so the following code will fail
// (Note: In Field Test 4, this restriction is temporarily canceled .)
// Var obj3 = new myobject ();
// Obj3.set ('value', 1000 );
----------
For more examples of attribute (), see testcase/baseobjectdemo2.html.
3. Use of the inherited (inherited) Method
----------
For an instance, obj. inherited () will call the parent class method.
Occurs in the parent class or even the ancestor class. When tobject () is called to the root class, because there is no method with the same name,
Therefore, an exception is returned.
In qomo, inherited is exactly the same as inherited in Delphi. Of course, it can only
Method. This includes the class (Declaration) method and object method. -- The difference between the two will be introduced later.
Inherited has three call methods (because it is always called within the method, this always points to the current instance ):
-This. inherited ():
-This. inherited (this. mehtodd [, Param]);
-This. inherited ('<methodname>' [, Param]);
The first method does not have any parameters. In this case, qomo searches for the parent class method of the current method and uses
Same entry parameter call. For the second and third methods, you can pass in a new parameter table. If
The parameter is ignored. The parameter table of the current method is also used.
The second and third methods are originally the same, but one is to use the method name, and the other is to use the method reference
Is the first parameter. There is no difference in efficiency between the two, but they are only used to meet different needs.
For how to inherit objects, you need to read relevant books about oop. Below
The example describes how to use this feature in qomo:
----------
Function animal (){
This. Leg = function (){
Alert ('run ');
}
This. Run = function (){
This. Leg ();
}
}
Function CAT (){
This. Jump = function (){
Alert ('jump ');
}
This. Run = function (){
This. Jump ();
This. Jump ();
This. inherited ();
}
}
Tanimal = Class (tobject, 'animal ');
Tcat = Class (tanimal, 'cat ');
OBJ = new CAT ();
OBJ. Run ();
----------
This example shows:
-"Animals" have a run behavior. The content of this behavior is (continuously) "Run (LEG )"
-"Cat" is an "animal" that inherits the run behavior from the "animal ".
-"Cat" is usually "Two hops" before continuing to run.
Therefore, the cat's run behavior description is:
----------
This. Run = function (){
This. Jump ();
This. Jump ();
This. inherited ();
}
----------
For more examples of inherited (), see testcase/baseobjectdemo3.html.
3. Class declaration period and Object Construction Period
----------
In all previous examples, I did not display one of the most important features of qomo to users. This is
"Class declaration period ". -- This annotation is left in front of most examples.
In qomo, the "constructor" written in user code should only have the "class declaration Syntax. So-called Class Declaration
Syntax refers to the syntax "only related to the performance of an object. Instead of adding too much logical code. Base
In this case, the class declaration can include the following code:
----------
Function myobject (){
Attribute (this, 'value', 0); // fast attribute Declaration
VaR v = _ Get ('data'); // obtain the feature value of the parent class (current class)
_ Set ('data', V); // sets the feature value, but does not overwrite the parent class
VaR CLS = _ Cls (); // get class reference
VaR COUNT = 10; // declare a class (private) static member
VaR Foo = function () {}; // declare a class private function
Function foo2 () {}; // same as above
This. Data = 123; // publish attributes
This. getvalue = function () {// read feature Method
This. Set (); // internal read Method
This. Get (); // internal write Method
}
This. setvalue = function () {// feature write Method
//...
}
This. Method1 = function () {// Class Method
This. inherited (); // inherit (CALL) the parent class Method
}
// (Other code ...)
}
Tmyobject = Class (tobject, 'myobject ');
----------
The above example includes the vast majority of code and its syntax for "class declaration cycle. Of course, in "other code ",
You can also add your own code. For example, initialize some features of the class, or add the class to the Global Monitor.
. However, you must note that in the "class declaration cycle ":
-This indicates the prototype of all object instances.
-You can use _ Cls () to obtain a reference of the class itself.
-You cannot directly operate on the attribute values declared by the current class (some restrictions may exist)
-You cannot add Port parameters to the (class declaration) constructor.
-This constructor function is executed only once.
For user code, the constructor cannot be added with port parameters, which restricts the use. But in fact
This is reasonable in the inheritance system. -- You cannot use the same class declaration to describe two different classes and instances.
In qomo, the user-declared "Constructor" is actually used as "class declaration ". Therefore, an object is independent.
Build cycle ". This cycle is completely controllable for user code:
----------
Function myobject (){
// (Omitted: Class Declaration)
This. Create = function (V1, V2, V3 ){
// Object Construction Period
}
}
Tmyobject = Class (tobject, 'myobject ');
----------
The object construction period is a function described by this. Create. It is also like the constructor in standard JS:
-Each object construction calls the this. Create () method for the instance.
-This method can have any entry parameter.
-This in this method directs to the object instance.
-In this method, Private Members and methods of the callback class can be used.
Therefore, users can write arbitrary JavaScript code here according to their own habits. However
Some syntax cannot be used here:
-Attribute (), _ set (), _ Get (), _ Cls () cannot be used
-This. getvalue () and so on cannot be declared as a feature
But there is a unique exception: This. inherited () can be used in the "object construction cycle:
----------
Function myobject (){
This. Method1 = function (){
//...
}
This. Create = function (V1, V2, V3 ){
// Object Construction Period
//...
If (! V1) return;
This. Method1 = function (){
This. inherited ();
}
}
}
Tmyobject = Class (tobject, 'myobject ');
----------
In this example, Method1 () in the "Object Construction Period" actually overwrites the "class. Method1" method. However
It does not change other instances constructed by other classes (if the V1 value is valid ). Therefore, "Object method" and "Class
Declared methods are differentiated.
Because of this distinction, you should know that if "object construction cycle" overwrites "class declaration method ()",
Then this inherited will call "method ". -- The semantics of inhreited () is "parent class method ".
For more information about this inherited () feature, see testcase/baseobjectdemo3.html.
Iii. Precautions for OOP syntax in Qomolangma
~~~~~~~~~~~~~~~~~~
First, the most important thing is that qomo's multi-vote Event System is "completely transparent" to any framework! Because
It can be embedded in any other framework like a normal event function (Response handle.
In fact, qomo's multi-vote event and qomo OOP framework are completely removed without any OOP features and framework features.
. -- This design concept fully embodies the objective and purpose of qomo and our awareness of OOP.
1. Some special cases and syntaxes of class declaration and Construction
----------
In qomo, class () can have only one parameter, namely <constructor Name>. There are two cases:
----------
// Syntax 1: The value is 'object' and is only reserved for the tobject declaration.
Function object (){
}
Tobject = Class ('object ');
// Syntax 2: The value is not 'object', which is equivalent to calling class (tobject, '<constructor Name> ');
Function myobject (){
}
Tmyobject = Class ('myobject ');
----------
In addition, class () has two possibilities:
----------
// Syntax 3: Class () called before Declaration
Tmyobject = Class (tobject, 'myobject ');
Function myobject (){
}
// Syntax 4: register only but do not declare a class
Function myobject (){
}
Class (tobject, 'myobject ');
----------
Syntax 3 uses the features of the Javascript compilation period. Because the declared function will be accepted during compilation,
Therefore, tmyobject's use of 'myobject' can appear before its declaration. However, the following method is used:
No (I have mentioned this in Qomolangma kernel (4 ):
----------
// Incorrect usage
Tmyobject = Class ('myobject ');
Myobject = function (){
}
----------
Syntax 4 utilizes the non-mandatory class declaration feature in qomo. This method only registers myobject () as a class,
Tmyobject is not a class type. In this case, you can still use OBJ = new myobject ()
To the class instance. For references that are completely equivalent to the class type tmyobject, they can be found in the following two places:
----------
OBJ = new myobject ();
// 1. class reference exists in OBJ. classinfo
Alert (obj. classinfo. classname );
// 2. This class reference exists in the namespace
VaR CLS = eval (obj. classinfo. spacename + '. tmyobject ');
Alert (CLS. classname );
----------
2. The qomo object is still constructed based on the prototype.
----------
Unlike some other OOP frameworks, the qomo object is still prototype-based. This indicates that the developer
You can still use prototype to modify attributes of the instance and constructor. It is important that this modification applies to the qomo class
The construction system will not have any negative impact. For example:
----------
Function myobject (){
Attribute (this, 'value', 200, 'R ');
}
Tmyobject = Class (tobject, 'myobject ');
Myobject. Prototype. value = 100;
VaR OBJ = new myobject ();
Alert (obj. value );
Alert (obj. Get ('value '));
----------
The qomo framework uses this "transparent to prototype inheritance" design, making it easier to embed it into other boxes.
Or in the system. In most cases, the third-party framework does not feel the existence of qomo, nor is it subject to the qomo syntax.
.
3. Second Syntax of qomo Object Construction
----------
First, as a habit, I implemented a "exactly the same as Delphi" syntax in qomo:
----------
Function myobject (){
}
Tmyobject = Class (tobject, 'myobject ');
VaR OBJ = tmyobject. Create ();
----------
As we can see, "Object = Class. Create ()" is more semantically consistent with "class inheritance system ". However, qomo
You do not want to impose any JavaScript-independent syntax or semantics on developers. Therefore, qomo still supports
The standard constructor syntax in Javascript is "Object = new Constructor ()". It must be noted that the two methods have
There is no difference between the object instances.
Another reason why qomo implements the "class. Create ()" syntax is that in the namespace, we store
Instead of constructor references. That is to say, the above tmyobject can be found in the namespace:
----------
CLS = <a_name_space>. tmyobject;
----------
In this case, we can only use the syntax "class. Create. Of course, in this case, there can still be two
Type:
----------
CLS = <a_name_space>. tmyobject;
// Method 1:
VaR obj1 = Cls. creae ();
// Method 2:
VaR obj2 = new Cls. Create ();
// Incorrect method:
// Var obj3 = new Cls ();
----------
Do not try to use the new () keyword for a class. In qomo, semantics like "New Cls ()" is incomprehensible.