在Java语言中,提供了发射机制,通过发射机制可以通过字符串构造出这个对象,可以获取对象的所有方法(包括私有方法),可以调用私有方法,可以更改成员变量的值(包括私有的成员变量)。
Ruby也是面向对象的高级语言,当然也提供了反射机制,今天我们讨论通过类名称构造类对象的功能。
我们先看普通的构造:
module ModuleA
#the class name, later we will use it to create the corresponding object
CLASS_NAME_OF_WOOD = "ModuleA::Wood"
CLASS_NAME_OF_WOODDESK = "ModuleA::WoodDesk"
CLASS_NAME_OF_WOODCHAIR = "ModuleA::WoodChair"
class Wood
def initialize
@desc = "I am a primal wood"
end
def say
puts @desc
end
end
class WoodDesk < Wood
def initialize
@desc = "I am a desk made of wood"
end
def say_private
puts "actually, i have some bug but no public"
end
public :say
private :say_private
end
class WoodChair < Wood
def initialize
@desc = "I am a chair made of wood"
end
def say_private
puts "I Want get married with a WoodDesk..."
end
def smile
puts "ha hah hah haha ...."
end
public :say
private :say_private, :smile
end
end
定义了一个基础类Wood,有两个子类:WoodDesk, WoodChair,子类有分别有一个私有方法 say_private。
我们new出对象来执行:
#the normal initailze
wood = ModuleA::Wood.new
wood.say
desk = ModuleA::WoodDesk.new
desk.say
chair = ModuleA::WoodChair.new
chair.say
#try call the private method
puts "desk respond to say_private? #{desk.respond_to? :say_private}"
desk.say_private if desk.respond_to? :say_private
上面代码,执行public方法say,然后尝试执行private方法 say_private,执行先check是否能够执行,返回结果是不能执行,desk.respond_to? :say_private返回false:
I am a primal wood
I am a desk made of wood
I am a chair made of wood
desk respond to say_private? false
好,现在我们通过反射机制来构造对象,并尝试执行其私有方法。
我们注意到模块的定义中有三个常量,定义的是类名称,
#the class name, later we will use it to create the corresponding object
CLASS_NAME_OF_WOOD = "ModuleA::Wood"
CLASS_NAME_OF_WOODDESK = "ModuleA::WoodDesk"
CLASS_NAME_OF_WOODCHAIR = "ModuleA::WoodChair"
下面会通过这三个变量来理解Module.constants方法。
下面代码片段,基于上面的类定义:
#get all module constants
obj_list = Array.new
tmp_const_sym_list = ModuleA.constants
tmp_const_sym_list.each do | sym |
obj_list << ModuleA.const_get(sym)
puts "calss = #{sym.class}, value = #{sym}"
end
我们注意到 ModuleA.constants,这个方法是Module模块中的,其作用是返回模块中所有常量的Symbol对象。我们看结果输出:
calss = Symbol, value = CLASS_NAME_OF_WOOD
calss = Symbol, value = CLASS_NAME_OF_WOODDESK
calss = Symbol, value = CLASS_NAME_OF_WOODCHAIR
calss = Symbol, value = Wood
calss = Symbol, value = WoodDesk
calss = Symbol, value = WoodChair
从结果中看到,定义的三个常量和类名称都被返回了。所以注意:Ruby中的常量是包含定义的常量(变量)和类名称,注意他们都是Symbol对象。。
不过我们是需要根据类名称构造类对象,那么那三个常量就是没用的,需要删除。我们通过正则表达式匹配名字,来过滤。上面的代码修改一下:
#get all module constants
sym_list = Array.new
tmp_const_sym_list = ModuleA.constants
tmp_const_sym_list.each do | sym |
puts "calss = #{sym.class}, value = #{sym}"
sym_list << ModuleA.const_get(sym) if /^Wood\w*/ =~ sym.to_s
end
sym_list << ModuleA.const_get(sym) if /^Wood\w*/ =~ sym.to_s,仅保存以Wood开头的symbol,这样我们就过滤掉了那三个常量。
找都类名称之后,开始构造对象:
#create object from symbol
obj_list = Array.new
sym_list.each do | sym |
obj = sym.new
obj_list << obj
puts "create the object: #{obj}"
end
begin
obj_list.each do | wood |
wood.say
end
调用Symbol的new方法构造出次对象(sym.new),然后我们调用对象的say方法:
create the object: #
create the object: #
create the object: #
I am a primal wood
I am a desk made of wood
I am a chair made of wood
达到了我们预期的结果。
本文链接:https://www.yunweipai.com/746.html
Ruby 和 Python比能否简单说点有什么特色的东西,还有Lua(看到有人写WireShark的插件)。
你们用到了?
这个有必要交流一下,哈哈。你教教我们python。
个人看法:
1、python用tab锁进来替代{},太难维护了;而ruby是 end,容易读。
2、ruby的block功能和强大。
3、ruby的API设计的很好用,如Array.delete_if(…)删除不符合条件的元素。
4、ruby支持re-open一个类,如你可以给string加方法。
python用 tab来格式化 这个毁誉参半 好处是编程规范 不过coding的兄弟基本上都是很不羁的
ruby的block确实很强大,非常灵活;完全是模版的一个超集 而且好象还是运行时检查的 这太变态了
ruby抽象得太夸张了,很多逻辑处理它都有现成的方法
老毛 ruby现在也是玩得很精了
除了第一条各有看法,剩下都有类似替代品.唉,人生苦短,用到在学吧
虽然加了框框,没有高亮,还是不好看:-)
管理员再改进改进?
你可以整一些python的上来,探讨探讨。
比如人家这个代码高亮做的好coolshell
1.给内建类添加方法,在网上找了个代码,以字符串为例
(有点搞笑,大概是hack了源码之后才搞出来的,实际代码中决不能这样做。)
import ctypes as c
_get_dict = c.pythonapi._PyObject_GetDictPtr
_get_dict.restype = c.POINTER(c.py_object)
_get_dict.argtypes = [c.py_object]
def get_dict(object):
return _get_dict(object).contents.value
#add method to a built in type
def sayHello(self):
print 'hello world'
get_dict(str)['sayHello'] = sayHello
"abc".sayHello()
python语法本身确实不能给内建的类做扩展,这样是为了保证最基本系统库的纯净,通常做法是继承他再搞个类。
2.
关于ruby的block,网上说比python lambda更强大,但没理解到精髓(这个可能涉及到高阶编程思想了,也许值得好好了解一下),
python只会这样的:
arr = ["d","a","b","c"]
arr.sort(lambda x,y: cmp(x,y))
3.类似delete_if,应当可以用python列表解析( List comprehensions)代替,
arr = [2,3,4,5,6]
newarr=[x%2 for x in arr]
列表解析提供的是更通用的一种方式,单独为delete_if提供api可能会让我再需要某个功能的时候就猜测,是不是还有multiple_if, tostr_if,记忆上会有负担:)
真是各有千秋吧,对比学习也不错,只要不是单纯的holy war,哈哈
可以参考:http://c2.com/cgi/wiki?PythonVsRuby
1、第一点,有一个专业术语:open class,意思是可以把一个class重新open。在某些场景下还是很有用的。比如你的代码中用到了String对象,你很想要一个方法但是原生的api不提供,你这种情况下就可以自己加一个方法。具体可以参考:http://blog.tektea.com/archives/299.html。
2、第二点,Python的lambda实际上和ruby中的Proc更象一些:
def gen_times(factor)
return Proc.new {|n| n*factor }
end
times3 = gen_times(3)
times5 = gen_times(5)
times3.call(12) #=> 36
times5.call(5) #=> 25
times3.call(times5.call(4)) #=> 60
我想Proc设计出来是弥补ruby在面向过程领域的缺陷。
不过在ruby1.9中也支持lambda。
我想大家都很迷惑ruby中的block,Proc,lambda,我整理一下到时候讨论。
3、第三点,我觉得是API封装的设计思想吧。
之前在martin fowler的博客上看到Java和ruby的API设计比较,Java也设计的很好,但是用起来,开发者要多写一些代码,ruby就方便一些。他举例了:
ary = Array.new
first = ary.first
last = ary.last
而Java的API,如ArrayList,就不提供获取第一个和最后一个元素的功能,需要开发者多写几行代码。
你说到对比学习,我想到在文学和历史和哲学领域,都有比较文学,比较历史学,比较哲学,就是拿同一个时代不同地域或不同文化的文学,历史,哲学思想来做比较,也很有意思的,能够得出不少规律。
我们可以搞一个比较编程,哈哈。
xiaoming的python炉火纯青了 啥时候发发python相关的
不敢不敢,一旦不在正式项目中用,很快就忘差不多了,再说从来对没有哪个工具敢说炉火纯青。等真有心得再来写。
对了你们都用mac,safari, 能不能说说有多爽~
mac主要有两点好处:
1、比较装B。
2、mac是unix的,对开发者比较方便。
mac还是看具体啥用途
safari结合触摸板操作体验 基本上碉堡了