2010-04-03 10:39:32 -04:00
|
|
|
# Test classes with a four-level inheritance chain.
|
2010-02-27 18:57:45 -05:00
|
|
|
class Base
|
|
|
|
func: (string) ->
|
2010-08-07 08:02:16 -04:00
|
|
|
"zero/#{string}"
|
2010-03-29 21:43:12 -04:00
|
|
|
|
2010-11-13 15:52:30 -05:00
|
|
|
@static: (string) ->
|
2010-08-07 08:02:16 -04:00
|
|
|
"static/#{string}"
|
2010-02-27 18:57:45 -05:00
|
|
|
|
|
|
|
class FirstChild extends Base
|
|
|
|
func: (string) ->
|
|
|
|
super('one/') + string
|
|
|
|
|
2010-09-27 23:59:47 -04:00
|
|
|
SecondChild = class extends FirstChild
|
2010-02-27 18:57:45 -05:00
|
|
|
func: (string) ->
|
|
|
|
super('two/') + string
|
|
|
|
|
2010-10-06 20:54:08 -04:00
|
|
|
thirdCtor = ->
|
|
|
|
@array = [1, 2, 3]
|
|
|
|
|
2010-02-27 18:57:45 -05:00
|
|
|
class ThirdChild extends SecondChild
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: -> thirdCtor.call this
|
2010-02-27 19:03:23 -05:00
|
|
|
|
|
|
|
# Gratuitous comment for testing.
|
2010-02-27 18:57:45 -05:00
|
|
|
func: (string) ->
|
|
|
|
super('three/') + string
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
result = (new ThirdChild).func 'four'
|
2010-02-27 18:57:45 -05:00
|
|
|
|
|
|
|
ok result is 'zero/one/two/three/four'
|
2010-03-29 21:43:12 -04:00
|
|
|
ok Base.static('word') is 'static/word'
|
2010-02-27 18:57:45 -05:00
|
|
|
|
2010-09-12 16:33:38 -04:00
|
|
|
FirstChild::func = (string) ->
|
|
|
|
super('one/').length + string
|
|
|
|
|
|
|
|
result = (new ThirdChild).func 'four'
|
|
|
|
|
|
|
|
ok result is '9two/three/four'
|
|
|
|
|
2010-10-06 20:54:08 -04:00
|
|
|
ok (new ThirdChild).array.join(' ') is '1 2 3'
|
|
|
|
|
2010-02-27 18:57:45 -05:00
|
|
|
|
|
|
|
class TopClass
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: (arg) ->
|
2010-07-24 22:23:37 -07:00
|
|
|
@prop = 'top-' + arg
|
2010-02-27 18:57:45 -05:00
|
|
|
|
|
|
|
class SuperClass extends TopClass
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: (arg) ->
|
2010-02-27 18:57:45 -05:00
|
|
|
super 'super-' + arg
|
|
|
|
|
|
|
|
class SubClass extends SuperClass
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: ->
|
2010-02-27 18:57:45 -05:00
|
|
|
super 'sub'
|
|
|
|
|
2010-06-29 21:03:50 -04:00
|
|
|
ok (new SubClass).prop is 'top-super-sub'
|
2010-02-28 00:13:17 -05:00
|
|
|
|
|
|
|
|
|
|
|
class OneClass
|
2010-11-13 15:52:30 -05:00
|
|
|
@new: 'new'
|
2010-10-06 20:07:19 -04:00
|
|
|
function: 'function'
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: (name) -> @name = name
|
2010-02-28 00:13:17 -05:00
|
|
|
|
|
|
|
class TwoClass extends OneClass
|
2010-11-12 00:20:08 -05:00
|
|
|
delete TwoClass.new
|
2010-02-28 00:13:17 -05:00
|
|
|
|
2010-09-08 20:25:17 -04:00
|
|
|
Function.prototype.new = -> new this arguments...
|
|
|
|
|
|
|
|
ok (TwoClass.new('three')).name is 'three'
|
2010-10-06 20:07:19 -04:00
|
|
|
ok (new OneClass).function is 'function'
|
|
|
|
ok OneClass.new is 'new'
|
2010-09-08 20:25:17 -04:00
|
|
|
|
|
|
|
delete Function.prototype.new
|
2010-04-03 10:39:32 -04:00
|
|
|
|
|
|
|
|
|
|
|
# And now the same tests, but written in the manual style:
|
2010-07-24 22:23:37 -07:00
|
|
|
Base = ->
|
|
|
|
Base::func = (string) ->
|
2010-04-03 10:39:32 -04:00
|
|
|
'zero/' + string
|
2010-07-24 22:23:37 -07:00
|
|
|
Base::['func-func'] = (string) ->
|
2010-08-07 08:02:16 -04:00
|
|
|
"dynamic-#{string}"
|
2010-04-03 10:39:32 -04:00
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
FirstChild = ->
|
2010-11-09 00:26:31 -05:00
|
|
|
SecondChild = ->
|
|
|
|
ThirdChild = ->
|
|
|
|
@array = [1, 2, 3]
|
|
|
|
this
|
|
|
|
|
|
|
|
ThirdChild extends SecondChild extends FirstChild extends Base
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
FirstChild::func = (string) ->
|
2010-04-03 10:39:32 -04:00
|
|
|
super('one/') + string
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
SecondChild::func = (string) ->
|
2010-04-03 10:39:32 -04:00
|
|
|
super('two/') + string
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
ThirdChild::func = (string) ->
|
2010-04-03 10:39:32 -04:00
|
|
|
super('three/') + string
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
result = (new ThirdChild).func 'four'
|
2010-04-03 10:39:32 -04:00
|
|
|
|
|
|
|
ok result is 'zero/one/two/three/four'
|
|
|
|
|
2010-06-29 21:03:50 -04:00
|
|
|
ok (new ThirdChild)['func-func']('thing') is 'dynamic-thing'
|
2010-05-31 22:32:43 -04:00
|
|
|
|
2010-04-03 10:39:32 -04:00
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
TopClass = (arg) ->
|
|
|
|
@prop = 'top-' + arg
|
2010-04-03 10:39:32 -04:00
|
|
|
this
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
SuperClass = (arg) ->
|
2010-04-03 10:39:32 -04:00
|
|
|
super 'super-' + arg
|
|
|
|
this
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
SubClass = ->
|
2010-04-03 10:39:32 -04:00
|
|
|
super 'sub'
|
|
|
|
this
|
|
|
|
|
|
|
|
SuperClass extends TopClass
|
|
|
|
SubClass extends SuperClass
|
|
|
|
|
2010-06-29 21:03:50 -04:00
|
|
|
ok (new SubClass).prop is 'top-super-sub'
|
2010-05-31 15:13:48 -04:00
|
|
|
|
|
|
|
|
|
|
|
# '@' referring to the current instance, and not being coerced into a call.
|
|
|
|
class ClassName
|
2010-11-11 23:04:58 -05:00
|
|
|
amI: ->
|
2010-05-31 15:13:48 -04:00
|
|
|
@ instanceof ClassName
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
obj = new ClassName
|
2010-06-12 19:05:13 -04:00
|
|
|
ok obj.amI()
|
2010-05-31 15:13:48 -04:00
|
|
|
|
|
|
|
|
|
|
|
# super() calls in constructors of classes that are defined as object properties.
|
|
|
|
class Hive
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: (name) -> @name = name
|
2010-05-31 15:13:48 -04:00
|
|
|
|
|
|
|
class Hive.Bee extends Hive
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: (name) -> super
|
2010-05-31 15:13:48 -04:00
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
maya = new Hive.Bee 'Maya'
|
2010-06-15 00:54:02 -04:00
|
|
|
ok maya.name is 'Maya'
|
|
|
|
|
|
|
|
|
|
|
|
# Class with JS-keyword properties.
|
|
|
|
class Class
|
|
|
|
class: 'class'
|
2010-06-15 01:03:14 -04:00
|
|
|
name: -> @class
|
2010-06-15 00:54:02 -04:00
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
instance = new Class
|
2010-06-15 01:03:14 -04:00
|
|
|
ok instance.class is 'class'
|
2010-06-15 01:28:30 -04:00
|
|
|
ok instance.name() is 'class'
|
|
|
|
|
|
|
|
|
|
|
|
# Classes with methods that are pre-bound to the instance.
|
2010-08-17 21:07:36 -04:00
|
|
|
# ... or statically, to the class.
|
2010-06-15 01:28:30 -04:00
|
|
|
class Dog
|
|
|
|
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: (name) ->
|
2010-07-24 22:23:37 -07:00
|
|
|
@name = name
|
2010-06-15 01:28:30 -04:00
|
|
|
|
|
|
|
bark: =>
|
2010-08-07 08:02:16 -04:00
|
|
|
"#{@name} woofs!"
|
2010-06-15 01:28:30 -04:00
|
|
|
|
2010-11-11 22:02:06 -05:00
|
|
|
@static = =>
|
2010-08-17 21:07:36 -04:00
|
|
|
new this('Dog')
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
spark = new Dog('Spark')
|
|
|
|
fido = new Dog('Fido')
|
|
|
|
fido.bark = spark.bark
|
2010-06-15 01:28:30 -04:00
|
|
|
|
|
|
|
ok fido.bark() is 'Spark woofs!'
|
2010-06-30 21:54:16 -04:00
|
|
|
|
2010-08-17 21:07:36 -04:00
|
|
|
obj = func: Dog.static
|
|
|
|
|
|
|
|
ok obj.func().name is 'Dog'
|
|
|
|
|
2010-06-30 21:54:16 -04:00
|
|
|
|
|
|
|
# Testing a bound function in a bound function.
|
|
|
|
class Mini
|
|
|
|
num: 10
|
|
|
|
generate: =>
|
2010-11-20 18:37:19 -05:00
|
|
|
for i in [1..3]
|
2010-06-30 21:54:16 -04:00
|
|
|
=>
|
|
|
|
@num
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
m = new Mini
|
2010-10-23 22:04:19 +09:00
|
|
|
eq (func() for func in m.generate()).join(' '), '10 10 10'
|
2010-07-12 22:42:21 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Testing a contructor called with varargs.
|
|
|
|
class Connection
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: (one, two, three) ->
|
2010-07-24 22:23:37 -07:00
|
|
|
[@one, @two, @three] = [one, two, three]
|
2010-07-12 22:42:21 -04:00
|
|
|
|
|
|
|
out: ->
|
2010-08-07 08:02:16 -04:00
|
|
|
"#{@one}-#{@two}-#{@three}"
|
2010-07-12 22:42:21 -04:00
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
list = [3, 2, 1]
|
|
|
|
conn = new Connection list...
|
2010-07-13 08:57:42 -04:00
|
|
|
ok conn instanceof Connection
|
2010-07-12 22:42:21 -04:00
|
|
|
ok conn.out() is '3-2-1'
|
2010-07-18 14:46:21 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Test calling super and passing along all arguments.
|
|
|
|
class Parent
|
2010-07-24 22:23:37 -07:00
|
|
|
method: (args...) -> @args = args
|
2010-07-18 14:46:21 -04:00
|
|
|
|
|
|
|
class Child extends Parent
|
|
|
|
method: -> super
|
|
|
|
|
2010-07-24 22:23:37 -07:00
|
|
|
c = new Child
|
2010-07-18 14:46:21 -04:00
|
|
|
c.method 1, 2, 3, 4
|
|
|
|
ok c.args.join(' ') is '1 2 3 4'
|
|
|
|
|
2010-07-18 14:22:07 -05:00
|
|
|
|
2010-07-27 07:03:44 -04:00
|
|
|
# Test classes wrapped in decorators.
|
|
|
|
func = (klass) ->
|
|
|
|
klass::prop = 'value'
|
|
|
|
klass
|
|
|
|
|
|
|
|
func class Test
|
|
|
|
prop2: 'value2'
|
|
|
|
|
|
|
|
ok (new Test).prop is 'value'
|
|
|
|
ok (new Test).prop2 is 'value2'
|
2010-07-27 22:05:55 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Test anonymous classes.
|
|
|
|
obj =
|
|
|
|
klass: class
|
|
|
|
method: -> 'value'
|
|
|
|
|
|
|
|
instance = new obj.klass
|
2010-09-18 22:25:45 -04:00
|
|
|
ok instance.method() is 'value'
|
|
|
|
|
|
|
|
|
|
|
|
# Implicit objects as static properties.
|
|
|
|
class Static
|
2010-11-11 22:02:06 -05:00
|
|
|
@static =
|
2010-09-18 22:25:45 -04:00
|
|
|
one: 1
|
|
|
|
two: 2
|
|
|
|
|
|
|
|
ok Static.static.one is 1
|
|
|
|
ok Static.static.two is 2
|
2010-09-27 23:59:47 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Nothing classes.
|
|
|
|
c = class
|
|
|
|
ok c instanceof Function
|
2010-10-06 20:54:08 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Classes with value'd constructors.
|
|
|
|
counter = 0
|
|
|
|
classMaker = ->
|
|
|
|
counter += 1
|
|
|
|
inner = counter
|
|
|
|
->
|
|
|
|
@value = inner
|
|
|
|
|
|
|
|
class One
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: classMaker()
|
2010-10-06 20:54:08 -04:00
|
|
|
|
|
|
|
class Two
|
2010-11-14 14:21:55 -05:00
|
|
|
constructor: classMaker()
|
2010-10-06 20:54:08 -04:00
|
|
|
|
|
|
|
ok (new One).value is 1
|
|
|
|
ok (new Two).value is 2
|
|
|
|
ok (new One).value is 1
|
|
|
|
ok (new Two).value is 2
|
2010-11-12 00:05:30 -05:00
|
|
|
|
|
|
|
|
|
|
|
# Exectuable class bodies.
|
|
|
|
class A
|
|
|
|
if true
|
|
|
|
b: 'b'
|
|
|
|
else
|
|
|
|
c: 'c'
|
|
|
|
|
|
|
|
a = new A
|
|
|
|
|
|
|
|
eq a.b, 'b'
|
|
|
|
eq a.c, undefined
|
|
|
|
|
|
|
|
|
|
|
|
# Light metaprogramming.
|
|
|
|
class Base
|
2010-11-13 15:52:30 -05:00
|
|
|
@attr: (name) ->
|
2010-11-12 00:20:08 -05:00
|
|
|
@::[name] = (val) ->
|
|
|
|
if arguments.length > 0
|
|
|
|
@["_#{name}"] = val
|
|
|
|
else
|
|
|
|
@["_#{name}"]
|
2010-11-12 00:05:30 -05:00
|
|
|
|
|
|
|
class Robot extends Base
|
|
|
|
@attr 'power'
|
|
|
|
@attr 'speed'
|
|
|
|
|
|
|
|
robby = new Robot
|
|
|
|
|
|
|
|
ok robby.power() is undefined
|
|
|
|
|
|
|
|
robby.power 11
|
|
|
|
robby.speed Infinity
|
|
|
|
|
|
|
|
eq robby.power(), 11
|
|
|
|
eq robby.speed(), Infinity
|
|
|
|
|
|
|
|
|
2010-11-28 10:08:49 -08:00
|
|
|
# Namespaced classes do not reserve their function name in outside scope.
|
|
|
|
one = {}
|
|
|
|
two = {}
|
|
|
|
|
|
|
|
class one.Klass
|
|
|
|
@label = "one"
|
|
|
|
|
|
|
|
class two.Klass
|
|
|
|
@label = "two"
|
|
|
|
|
|
|
|
eq typeof Klass, 'undefined'
|
|
|
|
eq one.Klass.label, 'one'
|
|
|
|
eq two.Klass.label, 'two'
|
2010-11-28 14:56:07 -08:00
|
|
|
|
|
|
|
|
|
|
|
# Nested classes.
|
|
|
|
class Outer
|
|
|
|
constructor: ->
|
|
|
|
@label = 'outer'
|
|
|
|
|
|
|
|
class @Inner
|
|
|
|
constructor: ->
|
|
|
|
@label = 'inner'
|
|
|
|
|
|
|
|
eq (new Outer).label, 'outer'
|
|
|
|
eq (new Outer.Inner).label, 'inner'
|