十一、多态性
因为Ruby是一种动态类型化语言,所以它不要求接口。其实,接口的力量完全存在于Ruby中,只是以一种更为灵活的方式存在而已。在Ruby中,有一个被昵称为“duck typing”的东西,借助于它,在Ruby中的多态性其实成了一种匹配方法名的问题。下面让我们比较一下Ruby和Java语言中的多态性实现。
(一) Java中的多态性
在Java语言中,展示多态性力量的方法之一是,声明一个接口类型并且让其它类型实现这个接口。然后,你可以把实现对象参考为这种接口类型并且调用在这个接口上的任何方法。作为一个例子,在列表13中,我定义了一个简单接口Filter:
列表13.一个简单Java接口
package com.vanward.filter;
public interface Filter {
boolean applyFilter(String value);
}
|
在列表14中,我定义了一个实现类,叫RegexPackageFilter,它使用一个正规表达式来实现过滤功能:
列表14.RegexPackageFilter实现了Filter
package com.vanward.filter.impl;
import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternCompiler;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Compiler;
import org.apache.oro.text.regex.Perl5Matcher;
import com.vanward.filter.Filter;
public class RegexPackageFilter implements Filter {
private String filterExpression;
private PatternCompiler compiler;
private PatternMatcher matcher;
public RegexPackageFilter() {
this.compiler = new Perl5Compiler();
this.matcher = new Perl5Matcher();
}
public RegexPackageFilter(final String filterExpression){
this();
this.filterExpression = filterExpression;
}
public boolean applyFilter(final String value) {
try{
Pattern pattrn = this.getPattern();
return this.matcher.contains(value, pattrn);
}catch(MalformedPatternException e){
throw new RuntimeException("Regular Expression was uncompilable " +
e.getMessage());
}
}
private Pattern getPattern() throws MalformedPatternException{
return compiler.compile(this.filterExpression);
}
}
|
现在,让我们设想存在Filter接口的多个实现(例如RegexPackageFilter,一个ClassInclusionFilter类型,也许还有一个SimplePackageFilter类型)。为了实现在程序中的最大灵活性,现在,其它的对象都可以参考这个接口类型(Filter)而不是实现者(implementer),详见列表15:
列表15.功能强大的多态性
private boolean applyFilters(final String value, final Filter[] filters){
boolean passed = false;
for(int x = 0; (x < filters.length && !passed); x++){
passed = filters[x].applyFilter(value);
}
return passed;
}
|
(二) Ruby中的多态性
在Ruby中,虽然没有接口,但是只要方法名匹配,你就可以使用多态性。
在列表16中,我用Ruby重建了一个Java的Filter类型。注意,每个类都没有联系(除了它们共享相同的方法apply_filter外)。的确,在实际开发中,应该为这两个类创建一个基类Filter;然而,在此,我想展示在没有类共享的情况下的多态性问题。
列表16.Ruby中的过滤实现
class RegexFilter
attr_reader :fltr_exprs
def initialize(fltr_exprs)
@fltr_exprs = fltr_exprs
end
def apply_filter(value)
value =~ @fltr_exprs
end
end
class SimpleFilter
attr_reader :fltr_exprs
def initialize(fltr_exprs)
@fltr_exprs = fltr_exprs
end
def apply_filter(value)
value.include?(@fltr_exprs)
end
end
|
注意,在列表16中,我可以通过RegexFilter的apply_filter()方法(经由=~语法)创建一个正规表达式匹配器。(如果你是一位Groovy用户,那么你现在应该很高兴,因为列表16展示了Groovy是如何深深地影响Ruby的)。