หน้าเว็บ

วันอาทิตย์ที่ 24 กุมภาพันธ์ พ.ศ. 2556

การสร้าง interface javascript

        ภาษา javascript เป็นภาษาที่ไม่มี interface ให้  เช่นเดียวกับการเขียน OOP ของภาษาอื่นๆ  อย่างเช่น java  

MyInterface.java
public interface MyInterface{
    public void method1();

    public int method2();

    public String method3(int input);
}
        ซึ่งภาษา java นั้นจะมี keyword interface ให้  ทำให้ developer สามารถที่จะสร้าง interface ขึ้นมาใช้งานเองได้อย่างง่ายดาย  ส่วนตัวที่เป็น implementation  ก็แค่ใช้ keyword implements  ก็จะสามารถเรียกใช้งาน interface นั้นๆได้แล้ว

MyImplementation.java
public class MyImplementation implements MyInterface{
    public void method1(){

    }

    public int method2(){
          
        return 0;   
    }

    public String method3(int input){

        return "";
    }
}
        ทีนี้เรามาดูกันครับว่า ถ้า javascript ไม่มี interface ให้เราจะต้องทำยังไง  หรือจะต้อง design  interface และ implementation ขึ้นมายังไง
1. การ design interface class

/**
 * @title : define interface javascript
 * @class : Interface
 * @author : redcrow
 * @create date : 25/02/2013
 * @modify date : 25/02/2013
 * @modify by : redcrow
 * @address : www.na5cent.blogspot.com
 */
var Interface = (function() {

    /**
    * private static method for check ensure constructor input type require
    */
    function _ensureConstructorRequire(name, methods) {
        if (typeof name !== 'string') {
            throw new Error("Constructor of Interface class require first argument is \"string\", but is \"" + (typeof name) + "\".");
        }

        if (Object.prototype.toString.call(methods) !== '[object Array]') {
            throw new Error("Constructor of Interface class require second argument is \"array of string\", but is \"" + (typeof methods) + "\".");
        }
    }

    /**
    * private static method for check ensure method type require
    */
    function _ensureMethodType(method, index) {
        if (typeof method !== 'string') {
            throw new Error("Constructor of Interface class require second argument is \"array of string\", but method index " + index + " is not \"string\", is \"" + (typeof method) + "\".");
        }

        return method;
    }

    /**
     * @constructor : require 2 arguments
     * 1. require => name(interface name : string).
     * 2. require => methods(array of method name : array of string).
     */
    return function(name, methods) {
        if (arguments.length !== 2) {
            throw new Error("Constructor of Interface class require 2 arguments => Interface(name(String), [methodName1(String), methodName2(String), ...]).");
        }
        _ensureConstructorRequire(name, methods);

        var _name = name;
        var _methods = [];

        for (var index = 0; index < methods.length; index++) {
            var method = _ensureMethodType(methods[index], index);
            _methods.push(method);
        }

        this.getName = function() {
            return _name;
        }

        this.getMethods = function() {
            return _methods;
        }
    }
})();
        code อาจจะดูยาวหน่อยครับ  นั่นเพราะ javascript เป็นภาษาที่เป็น dynamic  เราเลยต้องมีการตรวจสอบเงื่อนไขหลายๆอย่างเอง  เพื่อบังคับให้ developer implements interface  ตามที่เราได้ define ไว้อย่างถูกต้อง

        ซึ่งในที่นี้  input ที่จะถูกส่งเข้าไปมี 2 ตัวครับ
1. interface name  เป็น ชื่อของ interface นั้นๆ  บังคับว่าจะต้องเป็น string
2. array string ของ method name ว่าใน interface นี้  เราจะ define abstract method  อะไรไว้บ้าง

2. การตรวจสอบ implementation
/**
 * define public static method for check ensure class implements interfaces.
 */
Interface.ensureImplements = function(clazz, interfacs) {
    if (arguments.length !== 2) {
        throw new Error("Interface.ensureImplements require 2 arguments, Interface.ensureImplement(Class(Object), [Interface1(Object), Interface2(Object), ...]).");
    }

    if (typeof clazz !== 'object') {
        throw new Error("First argument of Interface.ensureImplements is not \"object\", but is \"" + (typeof clazz) + "\".");
    }

    if Object.prototype.toString.call(object) !== '[object Array]') {
        throw new Error("Second argument of Interface.ensureImplements is not \"array of Interface\", but is \"" + (typeof interfacs) + "\".");
    }

    for (var index = 0; index < interfacs.length; index++) {
        var interface = interfacs[index];
        if (interface.constructor !== Interface) {
            throw new Error("Second argument of Interface.ensureImplements index " + index + " is not Interface.");
        }

        var methods = interface.getMethods();
        for (var property in methods) {
            var method = methods[property];

            if (clazz[method] === undefined) {
                throw new Error("Implementation class is not define method \"" + method + "\" of Interface \"" + interface.getName() + "\".");
            }

            if (typeof clazz[method] !== 'function') {
                throw new Error("Implementation class define \"" + method + "\" is not \"method\", but is \"" + (typeof clazz[method]) + "\".");
            }
        }
    }
};
        ในส่วนนี้ก็เช่นกันครับ  เราจะต้องเขียน js code เพื่อมาตรวจสอบ implementation  ที่ทำการ implements interface นั้นๆ  เอง

3. การใช้งาน
/**
 * example to use
 */

/**
* define interface Shape
*/
var Shape = new Interface('Shape', ['drawLine', 'draw2D', 'draw3D']);

/**
* define class Circle
*/
var Circle = function() {

    this.drawLine = function() {

    }

    this.draw2D = function() {

    }

    //this.draw3D = function(){
        //will throw Error when not implement this method
    //}
};

var circle = new Circle();
try {
    Interface.ensureImplements(circle, [Shape]); //check implementation
} catch (e) {
    alert(e);
}
//

        ในที่นี้ implementation Circle จะมี error เกิดขึ้น  เนื่องจาก interface Shape  ได้ define method เอาไว้ 3 method คือ drawLine, draw2D และ draw3D  แต่ Circle  implements ไปแค่ 2 method  (draw3D comment
ไว้)  มันก็จะขึ้น Error แบบนี้ (แต่ถ้า implements ครบ  และ input ถูกต้องก็จะไม่มี Error)


        code ที่เขียนไว้  รองรับการ implements แบบ multiple interface  เราสามารถที่จะส่ง  class  เพื่อ implements กี่ interface ก็ได้  โดยส่ง interface เข้าใน  Interface.ensureImplements(circle, [Shape, ...]);  ในรูปของ Array[Interface1, Interface2, ...]


        แค่นี้เราก็มี interface ของ javascript ไว้ใช้งานเองแล้วครับ

ไม่มีความคิดเห็น:

แสดงความคิดเห็น