ES6里玩接口

OOP里,class和interface是很有用的两个东西,废话。
在JS/ES中,class被prototype取代,而interface则完全没影。
那么,class和interface到底有什么区别呢?

如果只是将class和interface看做是定义了一套方法的话,那么class和interface之间的区别大概只能看做是前者实现了方法(abstract的当然就没实现了),而后者没实现这套方法了。
所以class可以用作代码复用,而interface显然不能。
从这个角度来看的话,两者的区别的确不大。
不过这其实不是重点。
重点在于,从C++时代后开始,class不能多重继承就(C++里当然还是可以的),但interface却可以多重实现。
因此,class和interface的区别就体现了出来:class的作用更多的想是设计蓝图,而interface则是不同对象之间互动的协议。
也就是说,class规范了object的性质,而interface规范了object之间的交互
interface给出了在一个上下文环境中一个对象可以提供的服务,并且对于超出的部分不予理睬。

好了,明白了这点,就可以来搞一套虽然完全没什么意义但还是很好玩的ES6的实现了——

其实这套方案ES5里也能玩。

var ClassTest;

(function () {
    var id = 0;
    ClassTest = class {
        constructor (name) {
            var _id = id;
            this.name = name;
            Object.defineProperty(this, 'id', {
                configurable: false,
                enumerable: true,
                get: function () {
                    return _id;
                },
                set: function (nouse) {},
            });
            id ++;
            this.value = 0;
        }

        toString () {
            return "I'm " + this.name + ", the " + this.id + "nth child of THE DARK LORD!";
        }

        add (value) {
            this.value += value;
            return this;
        }
        minus (value) {
            this.value -= value;
            return this;
        }
        time (value) {
            this.value *= value;
            return this;
        }
        divide (value) {
            this.value /= value;
            return this;
        }

        Add (value) {
            this.value += value;
            return this.value;
        }
        Minus (value) {
            this.value -= value;
            return this.value;
        }
        Time (value) {
            this.value *= value;
            return this.value;
        }
        Divide (value) {
            this.value /= value;
            return this.value;
        }
    };
})();
var test1 = new ClassTest('Aloha'), test2 = new ClassTest('Kosmos');

class ClassOther {
    constructor () {
        this.name = "MiaoWu~~~";
        this.id = 0;
    }

    toString () {
        return "I'm Nothing...";
    }
}
var other = new ClassOther();

class Interface {
    constructor (kernel, options) {
        options = options || {};
        if (!!options.changable) {
            Object.defineProperty(this, 'kernel', {
                configurable: false,
                enumerable: false,
                writable: true,
                value: kernel,
            });
        }
        else {
            Object.defineProperty(this, 'kernel', {
                configurable: false,
                enumerable: false,
                get: function () {
                    return kernel;
                },
                set: function (nouse) {},
            });
        }
        if (!!options.frozen) {
            Object.freeze(this);
        }
    }

    get value () {
        if (isNaN(this.kernel.value)) return 0;
        else return this.kernel.value;
    }
    set value (nouse) {}
    get description () {
        if (!!this.kernel.toString) return this.kernel.toString();
        else return "EMPTY";
    }
    set description (nouse) {}

    add (value) {
        if (!!this.kernel.add) return this.kernel.add(value);
        else return this;
    }
    minus (value) {
        if (!!this.kernel.minus) return this.kernel.minus(value);
        else return this;
    }
    time (value) {
        if (!!this.kernel.time) return this.kernel.time(value);
        else return this;
    }
    divide (value) {
        if (!!this.kernel.divide) return this.kernel.divide(value);
        else return this;
    }

}

var int1 = new Interface(test1, { changable: true });
var int2 = new Interface(test2, { frozen: true });

在上面的例子中,我们先定义了两个类(ES6中的类基本可以看做Syntactic Sugar),然后构造了一个接口。
这个接口的作用非常简单,就是将真正的数据与操作行为分离开,从而操作层的错误操作不会影响到真正的数据。
事实上,这里我们完全可以再定义一个接口只实现Add、Minus、Time和Divide这四个函数。
从而我们可以看到,通过不同的接口,我们只能操作特定的方法、访问特定的属性,且任何在接口上的操作都不会影响到真正的数据——除非提供了方法让你去修改。
从而,这个模型就可以实现M与C的隔离。

其中还提供了两个参数,一个用来控制接口实例是否可以替换真正的数据,而另一个则控制接口实例是否可以拥有自己的属性。

从某种程度来说,这个Interface就是给一个真正的Data穿上了一件衣服,只露出那些想要露出的,而将那些不想露出的部分遮掩起来。

当然啦,最后还是要说:这套方案其实并没有什么真正的大用处——我直接访问Interface实例的kernel对象不就好了(当然这样的话一个很鸡贼的方式就是直接把所有方法与属性全部写在constructor里从而这个Interface没有prototype从而可以保证你访问不到kernel)。
毕竟ES不是OOP,硬将OOP中的东西弄到ES中很多时候是没必要的,反而破坏了ES本身Prototype Chain的美好——所以当我看到ES6里OOP的味道加重后总是感觉很不适应……(大家别理我这枚异端)

最后PS一下:上面所说的方案其实和ES6半毛钱关系都没有,在ES5里都能做到毫无障碍,科科。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容