一旦我有一个File http://ruby-doc.org/core-2.3.1/File.html例如,我想检查它是否匹配文件格式并且extend http://ruby-doc.org/core-2.3.1/Object.html#method-i-extend该实例具有相应的方法:
module MP3
def self.extended(base)
raise "Can only extend a File" unless base.is_a?(File)
raise "Incorrect file format" unless is_mp3?(base)
end
def self.is_mp3?(file)
# Full metadata check if it is a MP3 format
end
def year
# Extract year from metadata
end
end
song = File.new("song.mp3")
if MP3.is_mp3?(song)
song.extend(MP3)
puts song.ctime # Original File method
puts song.year # Extended MP3 method
end
picture = File.new("picture.jpg")
MP3.is_mp3?(picture) #=> False
picture.extend(MP3) #=> raise "Incorrect file format"
我想这不是传统的,但我的需求是:
- 能够处理多种文件格式。
- 在知道文件格式之前打开文件。
- 重复使用相同的
File
实例,而无需创建新对象。 (见下文)
- 两个原件都有
File
方法和格式化同一对象中的特定方法。
- 添加相应方法之前请检查文件格式是否正确。
这种做法正确吗?
这个问题是一个后续问题上一个问题 https://stackoverflow.com/questions/39934261/ruby-do-something-when-extending-an-instance-with-a-module.
我想扩展现有的File
实例而不是创建一个新实例,因为我正在使用包装器File
,它将整个文件保存在 RAM 中(从不允许顺序访问的磁带驱动器读取)。
您所提议的内容将太多选择要使用哪个类的逻辑放入调用者的代码中。每次添加新文件类型时,都需要更改使用代码的所有位置。
相反,使用工厂模式 https://en.wikipedia.org/wiki/Factory_method_pattern。编写一个类(工厂)来检查文件名并决定要做什么。除了我要使用更优越的Pathname http://ruby-doc.org/stdlib-2.3.1/libdoc/pathname/rdoc/Pathname.html.
require "pathname"
class Pathname::Format
def self.from_filename(filename)
path = Pathname.new(filename)
from_pathname!(path)
return path
end
def self.from_pathname!(path)
case path.extname
when ".mp3"
path.extend(MP3)
when ".jpg"
path.extend(JPG)
end
return
end
end
重点是将该决定放入工厂类中,而不是调用代码中。
然后你就可以编写你的模块了。
module JPG
def type
return "JPG"
end
end
module MP3
def type
return "MP3"
end
def year
puts "MP3 year called"
end
end
现在调用者只使用工厂。
# From a filename
song = Pathname::Format.from_filename("song.mp3")
puts song.ctime # Original File method
puts song.year # Extended MP3 method
# From a Pathname
picture = Pathname.new("picture.jpg")
Pathname::Format.from_pathname!(picture)
puts picture.type
与其使用大量特殊方法来检查对象是否属于特定类型,不如检查type
方法,检查它是否是一种模块,或者依赖鸭子打字 https://stackoverflow.com/questions/4205130/what-is-duck-typing#4205163.
if song.type == "MP3"
puts song.year
end
if song.kind_of?(MP3)
puts song.year
end
if song.respond_to?("year")
puts song.year
end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)