我正在玩J的面向对象设施。考虑以下非常人为的代码:
coclass 'Object'
create =: 3 : 'state =: 0'
increment =: 3 : 'state =: state + y'
destroy =: codestroy
cocurrent 'base'
objects =: (0 conew 'Object') , (0 conew 'Object') , 0 conew 'Object'
我想说我想在increment
数组中的每个对象上调用objects
方法。我怎么用J-tastic方式做到这一点?我能提出的唯一方法是中间动词:
o_increment =: 4 : 0
for_o. y do.
increment__o x
end.
)
3 o_increment objects
这可行,但不是很方便。还有更好的方法吗?
答案 0 :(得分:3)
因为对象引用是J的形态学的一部分,而不是语法,所以它们在运行时比其他数据更难操作。也就是说,对象引用被烘焙到名称中,而不是指定为自由参数。
因此,有两种方法可以在对象数组上调用方法,并且都需要显式代码。第一种方法 - 除了在特殊情况下很少使用 - 是生成并执行表示完全限定名称的字符串,包括直接(显式)位置。
3 apply&>~ 'increment_' ,L:0 objects ,&.> '_'
更常见的是在显式代码块中使用间接引用,使用其中一个预定义的局部变量作为locative。例如:
3 dyad def 'increment__y x'"0 objects
或等同于:
incrementObjs =: dyad define
increment__x y
)
objects incrementsObjs"0] 3
事实上,JSoftware在版本6中创建了一个主要backwards-compatibility-breaking change to the language,专门用于使这种模式更方便。以前(即在v6之前),您必须编写类似的内容:
incrementObjs =: dyad define
o =. x. NB. x and y used to be spelled x. and y.
increment__o y NB. but increment__x. would raise an error
)
在任何情况下,请注意,显式incrementsObjs"0 objects
循环的for_o. objects do.
重新制定实际上并不特定于OOP;它是J的阵列导向性质提供的标准迭代自动化。
这引出了我对你的问题的真正答案: J基本上是一种面向数组的语言,它的对象通常比Java等更熟悉的语言更粗糙。或C#。
在这些语言中,拥有一组对象是很常见的;在J中,拥有一个集合对象更常见。也就是说,在某种意义上,主流OOP语言中的对象是“小”#34;在J中,对象很大,因为J中的所有数据都很大(我并不是指物理"大数据",GB意义:我的意思是概念性的,哲学的,“感觉”。
因此,实际上最常见的表达问题的方式是:
coclass 'Object'
create =: 3 : 'state =: 0'
increment =: 3 : 'state =: state + y'
destroy =: codestroy
cocurrent 'base'
objects =: 'Object' conew 0 0 0
注意最后一行objects =: 'Object' conew 0 0 0
;原来是
objects =: (0 conew 'Object') , (0 conew 'Object') , 0 conew 'Object'
。
这是:我们创建了一个对象,而不是一个包含3个对象的数组,一个包含3个值的数组。
另请注意,是我更改的唯一代码行。 "重构"从处理标量值的对象转到管理任意数量值的数组的对象,需要零字节的代码更改。
但是增加所有对象呢?以前,你不得不说:
3 dyad def 'increment__y x'"0 objects
现在,您只需要说:
increment__objects 3
这就是为什么这是J 1 中OOP的标准方法。
1 嗯,愤世嫉俗的人可能会说J的基本数组性质在某种程度上消除了甚至与OOP的目标相冲突,并且J的功能可用于J在20世纪90年代后期OOP的升华期间,他们以一种事后的想法bol <<<咳嗽 Perl 咳嗽,但我没有愤世嫉俗。至少不公开。
OOP在J中占有一席之地,尤其适用于在动态系统中组织大型组件;它的使用方式与基本哲学是OO的语言不同,而不是AO。