ruby实现抽象类和抽象方法
程序员文章站
2022-03-11 09:37:52
...
ruby语言本身并没有提供abstract class和abstract method机制。这是ruby的spirit所决定的。但如果我们真的需要定义一个公共抽象类(或者抽象方法)来让子类来实现,又该如何做呢?
我们可以通过在调用方法时抛出NotImplementedError来防止方法被调用。如(来自《ruby cookbook》的例子):
父类Shape2D的方法area就是我们所需要的“抽象方法”了。你不能直接调用:
这样调用将抛出错误:Shape2D#area是抽象方法 (NotImplementedError)
Shape2D的子类Square覆写了此方法。由此我们模拟实现了抽象方法。那么抽象类该如何实现呢?自然而然,我们想到如果把类的initialize方法这样处理,那么这样的类将没办法被new生成,不正是我们所需要的抽象类?说干就干:
当你调用Shape2D.new时,解释器将提示你:Shape2D是抽象类(NotImplementedError)
我们已经实现了抽象方法和抽象类,感觉还是不够好,对每一个需要实现抽象类的类来说,我们都需要去写一句:raise NotImplementedError.new...实在不够爽。ruby鼓励我们去修改类的行为,甚至是标准库,那好,我们修改Class类吧,提供类似attr_reader的声明式服务:
OK,如此一来,我们的Shape2D可以写成:
尽管在ruby中,抽象类和抽象方法是否有用存在怀疑,不过知道这样的办法总是不错的主意
我们可以通过在调用方法时抛出NotImplementedError来防止方法被调用。如(来自《ruby cookbook》的例子):
class Shape2D
def area
raise NotImplementedError.new("#{self.class.name}#area是抽象方法")
end
end
class Square < Shape2D
def initialize(length)
@length = length
end
def area
@length ** 2
end
end
def area
raise NotImplementedError.new("#{self.class.name}#area是抽象方法")
end
end
class Square < Shape2D
def initialize(length)
@length = length
end
def area
@length ** 2
end
end
父类Shape2D的方法area就是我们所需要的“抽象方法”了。你不能直接调用:
s1=Shape2D.new
s1.area
s1.area
这样调用将抛出错误:Shape2D#area是抽象方法 (NotImplementedError)
Shape2D的子类Square覆写了此方法。由此我们模拟实现了抽象方法。那么抽象类该如何实现呢?自然而然,我们想到如果把类的initialize方法这样处理,那么这样的类将没办法被new生成,不正是我们所需要的抽象类?说干就干:
class Shape2D
def initialize
raise NotImplementedError.new("#{self.class.name}#area是抽象类")
end
def area
raise NotImplementedError.new("#{self.class.name}#area是抽象方法")
end
end
def initialize
raise NotImplementedError.new("#{self.class.name}#area是抽象类")
end
def area
raise NotImplementedError.new("#{self.class.name}#area是抽象方法")
end
end
当你调用Shape2D.new时,解释器将提示你:Shape2D是抽象类(NotImplementedError)
我们已经实现了抽象方法和抽象类,感觉还是不够好,对每一个需要实现抽象类的类来说,我们都需要去写一句:raise NotImplementedError.new...实在不够爽。ruby鼓励我们去修改类的行为,甚至是标准库,那好,我们修改Class类吧,提供类似attr_reader的声明式服务:
class Class
def
abstract(*args)
args.each do |method_name|
define_method(method_name) do |*args|
if method_name == :initialize
msg = "#{self.class.name}是抽象类"
else
msg = "#{self.class.name}##{method_name}是抽象方法"
end
raise NotImplementedError.new(msg)
end
end
end
end
def
abstract(*args)
args.each do |method_name|
define_method(method_name) do |*args|
if method_name == :initialize
msg = "#{self.class.name}是抽象类"
else
msg = "#{self.class.name}##{method_name}是抽象方法"
end
raise NotImplementedError.new(msg)
end
end
end
end
OK,如此一来,我们的Shape2D可以写成:
class Shape2D
abstract:initialize,:area #initialize和area是抽象方法
end
abstract:initialize,:area #initialize和area是抽象方法
end
尽管在ruby中,抽象类和抽象方法是否有用存在怀疑,不过知道这样的办法总是不错的主意
上一篇: 使用axios封装fetch方法和调用
下一篇: 机器人判断人是否接近
推荐阅读
-
微信小程序下拉加载和上拉刷新两种实现方法详解
-
C#自定义繁体和简体字库实现中文繁体和简体之间转换的方法
-
kNN算法python实现和简单数字识别的方法
-
vue-cli整合vuex的时候,修改actions和mutations,实现热部署的方法
-
PHP 面向对象程序设计(oop)学习笔记(一) - 抽象类、对象接口、instanceof 和契约式编程
-
PHP OPP机制和模式简介(抽象类、接口和契约式编程)
-
python实现去除下载电影和电视剧文件名中的多余字符的方法
-
Python实现插入排序和选择排序的方法
-
python 给DataFrame增加index行名和columns列名的实现方法
-
Anaconda2下实现Python2.7和Python3.5的共存方法