Javascript乱弾設計モードシリーズ(0)-対象基礎及びインターフェースと継承類の実現


理論知識
1.まずJavascriptは弱いタイプの言語で、変数を定義する時は声明のタイプは必要ありません.例えば、var Person=new Person()のように、変数のタイプは「var」です.今のC鑰3.0もこの匿名タイプの概念を導入しています.弱いタイプの変数は非常に柔軟性があります.Javascriptは必要に応じてタイプを変換します.したがって、これは遅いバインディングの方法を採用することを決定しました.すなわち、実行後に変数の種類を知ることができます.
2.対象に向かう概念は言うまでもなく、パッケージ、継承、多状態である.
3.Javascriptオブジェクトのタイプは主に三つに分けられます.ローカルオブジェクト、例えばString、Aray、Dateなどです.Global,Mathなどのオブジェクトを内蔵します.宿主の対象は、BOM、DOMの対象などです.変数の範囲は、従来のオブジェクト指向プログラム設計における作用領域を含み、公有、保護、私有、静的など.
 
主な内容
1.Javascriptがどのようにオブジェクトを作成したかを見てみましょう.
function Man() {
   //  
}
Man.prototype.getNickName = function() {
    return "Leepy";
}; 

var man = new Man();
var name = man.getNickName(); 
 このようにして、最も簡単なクラスとオブジェクトを作成しました.ここでfunction Man(){}をMan類の構造関数と見なし、getNickName()をMan類と見なす方法は、正確にはMan類の公共方法として考えられます.なぜですか?それはJavascriptが実際に共有している区分が一つもないので、開発者が自分でこのようなルールを指定しました.ここでMan類のリストを完全に並べます.
 
function Man() {
    //       
    var Sex = " ";
    //      
    function checkSex() {
        return (Sex == " ");
    }
    //    
    this._getSex = function() {
        //        
        if(checkSex())
            return " ";
        else
            return " ";
    }
    //    
    this.getFirstName = function() { 
        return "Li";
    };
    //    
    this.getLastName = function() {
        return "Ping";
    };
}
//    
Man.prototype.getNickName = function() {
    return "Leepy";
};
//    
Man.prototype.getFullName = function() {
    return this.getFirstName() + " " + this.getLastName();
};
//    
Man.prototype.getSex = function() {
    //      
    return this._getSex();
};
//      
Man.say = function() {
    return "Happy new year!";
}
 
このような種類は伝統的な種類と似ているように見えますか?
 
2.次のこれは本編の一つのポイントです.Javascriptでインターフェースをどのように設計し、それをクラスに引き継がせますか?
まず、伝統的なC〓言語はどのようにインタフェースを設計しているかを見ましょう.
public interface Person
{
    string GetName();
    void SetName(string name);
}
public class Man : Person
{
    private string _name; 

    public string GetName()
    {
        return _name;
    }
    public void SetName(string name)
    {
        _name = name;
    }
} 
 
インターフェースでは、属性、方法、イベント、タイプを宣言することができますが、変数を宣言することはできません.しかし、これらのメンバーの具体的な値を設定することはできません.つまり、定義するだけで、定義されたものに値を付けることはできません.インターフェースは、その後継クラスまたは派生クラスの規約として、継承クラスまたはその派生クラスは、インターフェース属性、方法、方法、イベントとタイプの具体的な実装は、ここでGetName()は、SetName()は、メソッド名と属性呼び出し順序とが一致しているためである.
 
このようなインターフェースベースの思想があります.Javascriptのインターフェースクラスを設計する時もこの仕様を考慮しなければなりません.まずメインJSファイルの呼び出しから話します.
 
var Person = new Interface("Person", [["getName", 0], ["setName", 1]]); 
 
このうち、Interface類は後で言うインターフェース類で、最初のパラメータ「Person」はインターフェース類の名称で、二つ目のパラメータは二次元配列で、「getName」はインターフェース方法の名前で、「0」はこの方法が持つパラメータの個数です.同理このようなインターフェースが定義されました.どう使いますか?
function Man() 
{
    this.name = "";
    Interface.registerImplements(this, Person);
}
Man.prototype.getName = function() {
    return this.name;
};
Man.prototype.setName = function(name) {
    this.name = name;
}; 
 
Manの構造関数に含まれているのを見ました.
Interface.register Implements(this、Person);
これは、実用化されたthisオブジェクトをPersonインターフェースに継承し、クラスを引き継いでインターフェースを行う方法である.
コードはクリアでシンプルに見えますか?では、本格的なコアコードInterface.jsを紹介します.
まず、Interfaceの構造関数の部分を見ます.

function Interface(name, methods) 
{
    if(arguments.length != 2) {
        throw new Error("       " + arguments.length + "   ,    2   .");
    }
    this.name = name;
    this.methods = [];
    if(methods.length < 1) {
        throw new Error("         .");
    }
    for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i][0] !== 'string') {
            throw new Error("                   .");
        }
        if(methods[i][1] && typeof methods[i][1] !== 'number') {
            throw new Error("                  .");
        }
        if(methods[i].length == 1) {
            methods[i][1] = 0;
        } 

        this.methods.push(methods[i]);
    }    
};

 
 
先ほどvar Person=new Interfaceを見ました.ここで二つのパラメータを別々に保存します.
コール方法の一部:
Interface.registerImplements = function(object) { 

    if(arguments.length < 2) {
        throw new Error("           2   .");
    } 

    for(var i = 1, len = arguments.length; i < len; i++) {
        var interface = arguments[i];
        if(interface.constructor !== Interface) {
            throw new Error("  2             .");
        }
        for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
            var method = interface.methods[j][0];
            if(!object[method] || typeof object[method] !== 'function' || object[method].getParameters().length != interface.methods[j][1]) {
                throw new Error("           " + interface.name + "     " + method + ",           .");
            }
        }
    }
}; 
 
先ほどのこのInterface.register Implements;実際にここでは、thisオブジェクトの方法名とパラメータの個数を、Personに保存されたばかりのmethodsと逐一比較しています.見つけられないか、合わないかは、エラーを警告します.ここで、object[method].get Parameeters().lengthは、以下のコードを呼び出します.
 
Function.prototype.getParameters = function() { 

    var str = this.toString();
    var paramString = str.slice(str.indexOf('(') + 1, str.indexOf(')')).replace(/\s*/g,'');     //       
    try
    {
        return (paramString.length == 0 ? [] : paramString.split(','));
    }
    catch(err)
    {
        throw new Error("     !");
    }
} 
 
 
 getParameters()メソッドは、Functionオブジェクトの拡張として機能し、メソッドに含まれるパラメータ配列を取得する.
Interface.jsの完全なコードは以下の通りです.
 
Interface.js  
function Interface(name, methods) 
{
    if(arguments.length != 2) {
        throw new Error("       " + arguments.length + "   ,    2   .");
    }
    this.name = name;
    this.methods = [];
    if(methods.length < 1) {
        throw new Error("         .");
    }
    for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i][0] !== 'string') {
            throw new Error("                   .");
        }
        if(methods[i][1] && typeof methods[i][1] !== 'number') {
            throw new Error("                  .");
        }
        if(methods[i].length == 1) {
            methods[i][1] = 0;
        } 

        this.methods.push(methods[i]);
    }    
}; 

Interface.registerImplements = function(object) { 

    if(arguments.length < 2) {
        throw new Error("           2   .");
    } 

    for(var i = 1, len = arguments.length; i < len; i++) {
        var interface = arguments[i];
        if(interface.constructor !== Interface) {
            throw new Error("  2             .");
        }
        for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
            var method = interface.methods[j][0];
            if(!object[method] || typeof object[method] !== 'function' || object[method].getParameters().length != interface.methods[j][1]) {
                throw new Error("           " + interface.name + "     " + method + ",           .");
            }
        }
    }
}; 

Function.prototype.getParameters = function() { 

    var str = this.toString();
    var paramString = str.slice(str.indexOf('(') + 1, str.indexOf(')')).replace(/\s*/g,'');     //       
    try
    {
        return (paramString.length == 0 ? [] : paramString.split(','));
    }
    catch(err)
    {
        throw new Error("     !");
    }
} 
 
 
もう一つのhtmlページを作成して効果を試してみます.
 
<script type="text/javascript">
function test()
{
    var man = new Man();
    man.setName("Leepy");
    alert(man.getName());
}
</script> 

<input type="button" value="click" onclick="test();" />
 
 
最終結果は、「Leepy」のポップアップボックスです.
ここでもう一つのポイントを強調したいのですが、もしインターフェース上の方法が継承クラスで完全に実現されていない場合、あるいは方法パラメータの個数が一致しない場合、エラーを提示します.3.もし私が他のクラスに継承したいなら、どうすればいいですか?例を見続けて、ここでSchoolBoy(男子学生)クラスを定義します.
 
function SchoolBoy(classNo, post)
{
    Man.call(this);
    this._chassNo = classNo;
    this._post = post;
}
SchoolBoy.prototype = new Man();
SchoolBoy.prototype.getName = function() {
    return "Mr " + this.name;
}
SchoolBoy.prototype.setName = function(name) {
    this.name = name + "'s";
}
 
 
そのうちMan.cal(this);実際にManのキーワードthisをSchoolBoyのオブジェクトに割り当てます.SchoolBoyはManの構造関数のname属性を持っています.
School Boy.prototype=new Man()実際にManのprototypeをSchoolBoy.prototypeに値付けします.School BoyはManの種類の中の方法があります.
後に続くgetName()、setName()は、実際にManクラスを継承する前の方法をカバーしています.
そして効果を見ます.
var schoolboy = new SchoolBoy("    ", "  ");
schoolboy.setName("   ");
alert(schoolboy.getName());
Code highlighting produced by Actipro CodeHighlighter(freew)
http://www.CodeHighlighter.com/


最後の結果は「Mr周杰倫's」のポップアップボックスです.
締め括りをつける
この文章は主にいくつかのJavascriptが対象に向かう基礎とインターフェースと継承類の実現などを述べます.次のページは本格的なJavascriptデザインモードの征途を開始します.そして、いくつかのウェブサイトシステムの実例と関連して話します.
 
 
本論文はhttp://www.cnblogs.com/liping13599168/archive/2009/01/03/1367334.htmlから来ている.