论坛首页 Web前端技术论坛

忘记 prototype,使用 Modello 来编写类

浏览 20642 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-04-10  
JavaScript 让人又爱又恨。爱的是她使用起来非常方便,三两个语句就可以实现一个用户交互操作。恨的是她太过灵活,又没有标准的类库,以致于在大型的项目中使用和维护起来非常困难。

相信很多人初学 JavaScript 的人都领教过 prototype 的晦涩,特别是对于有过其它面向对象编程语言使用经验的程序员来说,prototype 的继承机制大大地限制了他们设计技巧。

一种编程语言决定一种思维方式。同一个模型如果用 C 语言来实现,你只会小心翼翼地把玩内存块和指针;如果用 java 来实现,你可以轻轻松松地使用类来描绘这个模型中的各个实物。

在 JavaScript 中,你想创建一个新类,并继承一个现有的类。你必须首先生成父类的一个实例,然后将这个实例设为子类构造函数的 prototype。这是一种奇怪的思维方式,我明明在设计类,怎么我必须创建实例呢?在这个实例的创建过程中会不会发生我意想不到的事情呢?

很多人试图避开这个奇怪的语法,我也是其中之一。方法无非就是编写一个函数来封装这个继承过程。这样的方法有很多,本人觉得比较好的是 json 作者在文章 Classical Inheritance in JavaScript 中提到的 inherits 方法。

我的想法是,干脆不用 prototype,使用现有的语言设施类模拟整个构造实例的过程,从而实现真正意义上的继承,甚至多继承,接口等等。

Modello 就是基于这种思想写出来的。使用它来编写类,可以让你编写更高质量、更模块化的 JavaScript 代码。它还有其它特性,例如私有成员、类型鉴别、多继承等等。使用 Modello 编写的类库,甚至可以使用 Max-in 方式或者 Plug-in 的方式来扩展。

欢迎对这方面有兴趣朋友来和我一起讨论:)
   发表时间:2006-04-11  
这里有一篇介绍文章:http://www.ajaxwing.com/index.php?id=2
0 请登录后投票
   发表时间:2006-04-11  
简单看了一下,清爽的很,希望楼主在多介绍一下,讲讲自己的心得。。。关注
0 请登录后投票
   发表时间:2006-04-11  
在第二楼哪里有一篇详细的介绍文章,可以去看一下。

我个人比较喜欢 Python,所以细心的你会发现 Modello 的某些功能有点跟 Python 相似,比方说多继承,可以用来写 Mix-in。

在这里举几简单的例子:

/*
* 创建一个类 C1,不继承自任何类
* 沿用 Prototype 的编写类的写法
*/
var C1 = Class.create();;

/*
* 构造函数
*/
C1.construct = function(); {
  var _private_member = ...;
  this.public_member = ...;
  // 初始化函数
  this.initialize = function(); {
    ...
  }
}

/*
* 创建一个类 C2,继承自 C1
*/
var C2 = Class.create(C1);;
C2.construct = function ($self); {
  ...
  this.initialize = function(); {
    // 调用父类的初始化方法
    $self.super0.initialize.call(this);;
    ...
  }
}

/*
* 管理类的函数
*/
// 其中,kenxu 可以理解为命名空间
Class.register(C1, 'kenxu.C1');;
// 也可以这样连写
Class.create();.register('kenxu.C1');;
// 获取类
var C = Class.get('kenxu.C1');;

/*
* 创建类的实例
*/
var C = Class.get('kenxu.C1');;
var obj = new C;
// 连写技巧
var obj = Class.get('kenxu.C1');.create();;


我自己使用 Modello 的最大心得,就是让我可以在 JavaScript 中,继续运用以往掌握的面向对象设计技巧,而不需要换另一种思维方式。

谢谢关注:)
0 请登录后投票
   发表时间:2006-04-22  
OO JavaScript来编写类也可以参考一下http://j2s.sourceforge.net/j2sclazz/及其依赖的Java2Script(http://j2s.sourceforge.net/)技术
0 请登录后投票
   发表时间:2006-04-22  
jossonsmith 写道
OO JavaScript来编写类也可以参考一下http://j2s.sourceforge.net/j2sclazz/及其依赖的Java2Script(http://j2s.sourceforge.net/)技术


to: jossonsmith

花了一个小时了解 j2s,感觉这个项目很棒!

我最欣赏的地方,就是可以用 java 的语法来编写 JavaScript。

我是在去年10月份左右开始学习 JavaScript 的,当时觉得使用 JavaScript 来进行面向对象编程特别扭,于是到处去找有关相关的资料。最开始找到的是 Prototype,因为他的名字特别响。但是用着用着才发现,Prototype 最有价值的地方是提供了特别好用的函数,而不是使 JavaScript 变得更加面向对象。

然后我找到的是 AtlasAtlas 的语法很漂亮,立刻让我折服。但用起来却很不爽,洋洋洒洒几千行的基础代码,语法也不够简洁。

在后来我找到《Classical Inheritance in JavaScript》,文章中介绍的方法我认为是最精巧的。但语法不够漂亮,而且我测试过,在一些复杂的继承链下还会出错。

后来,我决定综合各家所长,编写一套简洁、漂亮、轻巧的面向对象基础库。于是就有了 Modello

再后来,我还接触了 JSVMWt,直到现在的 j2sclazz。这些项目的观点给了我很大的启发,别开新面。

回到 j2sclazz,我想给出一个例子,这个例子我在很多套库上测试都是失败的。所以我想考考 jossonsmith:)

Modello 编写,代码是这样的:


// 打印函数
var trace = function (str); {
    document.write(str + '<br />');;
}

// 基类 C1
var C1 = Class.create();;
C1.construct = function (); {
    this.initialize = function (); {
        trace('C1.initialize call.');;
    }
}

// C2 继承 C1
var C2 = Class.create(C1);;

// C3 继承 C2
var C3 = Class.create(C2);;

// C4 继承 C3
var C4 = Class.create(C3);;
C4.construct = function ($self); {
    this.initialize = function (); {
        // 调用父类的初始化参数
        $self.super0.initialize.call(this);;
        trace('C4.initialize call.');;
    }
}

// C5 继承 C4
var C5 = Class.create(C4);;
C5.construct = function ($self); {
    this.initialize = function (); {
        // 调用父类的初始化参数
        $self.super0.initialize.call(this);;
        trace('C5.initialize call.');;
    }
}

new C5;



这个例子实际上是要考验,经过复杂的继承关系后, super 使用的正确性。正常的情况下输出应该是这样的:


C1.initialize call.
C4.initialize call.
C5.initialize call.



运行上面的例子:Modello Example: Single Inheritance

请问 j2sclazz 是否能实现上面的例子呢?如果能实现,请贴出代码。欢迎对 OO JavaScript 有兴趣的朋友都来一起讨论。
0 请登录后投票
   发表时间:2006-04-23  
JavaScript & HTML codes:

http://j2s.sourceforge.net/demo/constructor-test.html

<html>
    <head>
        <title>Tests on Object Oriented Programming in JavaScript</title>
    </head>
<body>
<script type="text/javascript" src="http://j2s.sourceforge.net/j2sclazz/0.6.1/commented/j2sclazz.js"></script>
<script type="text/javascript">
System = {};
System.out = {};
System.err = {};
System.out.println = System.err.println = function (str); {
	document.body.appendChild (document.createTextNode (str););;
	document.body.appendChild (document.createElement ("BR"););;
};
</script>
<script type="text/javascript">
// The following JavaScript codes are genereted by Java2Script Pacemaker 1.0.0 M1
Clazz.declarePackage ("javaeye");;
cla$$ = javaeye.C1 = function (); {
Clazz.instantialize (this, arguments);;
};
Clazz.decorateAsType (cla$$, "javaeye.C1");;
Clazz.makeConstructor (cla$$, 
function (); {
System.out.println ("C1.initialize call.");;
});;
cla$$ = javaeye.C2 = function (); {
Clazz.instantialize (this, arguments);;
};
Clazz.decorateAsType (cla$$, "javaeye.C2", javaeye.C1);;
cla$$ = javaeye.C3 = function (); {
Clazz.instantialize (this, arguments);;
};
Clazz.decorateAsType (cla$$, "javaeye.C3", javaeye.C2);;
cla$$ = javaeye.C4 = function (); {
Clazz.instantialize (this, arguments);;
};
Clazz.decorateAsType (cla$$, "javaeye.C4", javaeye.C3);;
Clazz.makeConstructor (cla$$, 
function (); {
Clazz.superConstructor (this, javaeye.C4);;
System.out.println ("C4.initialize call.");;
});;
cla$$ = javaeye.C5 = function (); {
Clazz.instantialize (this, arguments);;
};
Clazz.decorateAsType (cla$$, "javaeye.C5", javaeye.C4);;
Clazz.makeConstructor (cla$$, 
function (); {
Clazz.superConstructor (this, javaeye.C5);;
System.out.println ("C5.initialize call.");;
});;
Clazz.defineMethod (cla$$, "main", 
function (args); {
 new javaeye.C5 ();;
}, "Array");;
cla$$.main = cla$$.prototype.main;
// The above JavaScript codes are genereted by Java2Script Pacemaker 1.0.0 M1
</script>
<script type="text/javascript">
javaeye.C5.main([]);;
</script>
</body>
</html>


Java source codes:

http://j2s.sourceforge.net/demo/javaeye/C5.java

package javaeye;

class C1 {
	public C1(); {
		System.out.println("C1.initialize call.");;
	}
}

class C2 extends C1 {}

class C3 extends C2 {}

class C4 extends C3 {
	public C4(); {
		super();;
		System.out.println("C4.initialize call.");;
	}
}

public class C5 extends C4 {
	public C5(); {
		super();;
		System.out.println("C5.initialize call.");;
	}
	public static void main(String[] args); {
		new C5();;
	}
}
0 请登录后投票
   发表时间:2006-04-23  
Java2Script基本上实现了全部Java的语法(包括Java5.0的语法),但一些偏僻的语法,譬如循环引用等,但对于面向对象的单根继承、多态、final变量、同名member的处理都是十分全面的,同时在Java内置库方面(譬如java.util.*)支持也是很好的。

对OOP in JS感兴趣的,可以尝试一把。
0 请登录后投票
   发表时间:2006-04-23  
to: jossonsmith

首先,谢谢你详细的回复,希望能看到有关 j2s 的更多中文文档,因为我是个很懒的中国人,呵呵!

to: 各位

如果你是 java 程序员,我强烈建议你使用 j2s

如果你不是,那么我还是建议你用 Modello

看看上面关于继承的三个代码,从简单程度、可读性、美观等方面对比,明显是:

java &gt; Modello &gt; j2sclazz

而且,Modello 只有两百多行的代码,支持多继承。。。我怎么自卖自夸起来了,ft!
0 请登录后投票
   发表时间:2006-04-23  
Java2Script衍生出来的J2SClazz本来就为Java的全部语言特性而写的,主要功夫花在函数“多态”和强类型模拟的实现上面,所以相对来说比较复杂。

如果追求简洁的话,也不妨参考另外一个大牛写的“A Base Class for JavaScript Inheritance”
http://dean.edwards.name/weblog/2006/03/base/
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics