问题描述
很多时候,我发现自己(似乎是)在从抽象集合类继承时将成分和继承结合在一起,我忍不住觉得这在技术上是相互矛盾的设计范式它。
/** Custom String List implementation */
public class MyStringList extends AbstractList<String>
{
private final AbstractList<String> _myStringList;
public MyStringList()
{
this._myStringList = new ArrayList<String>();
}
public MyStringList(Collection<String> stringCollection)
{
if (stringCollection.contains(null))
{
throw new NullPointerException("Null values not permitted in MyStringList");
}
else
{
this._myStringList = new ArrayList<String>(stringCollection);
}
}
@Override
public String get(int index)
{
return this._myStringList.get(index);
}
@Override
public int size()
{
return this._myStringList.size();
}
@Override
public String set(int index,String aString)
{
++this.modCount;
return this._myStringList.set(index,Objects.requireNonNull(aString));
}
@Override
public void add(int index,String aString)
{
++this.modCount;
this._myStringList.add(index,Objects.requireNonNull(aString));
}
@Override
public boolean add(String aString)
{
++this.modCount;
return this._myStringList.add(Objects.requireNonNull(aString));
}
@Override
public String remove(int index)
{
++this.modCount;
return this._myStringList.remove(index);
}
// Method to make this list implementation distinct from ArrayList for the sake of
// this StackOverflow question example
public String[] getNumericContaining()
{
return this._myStringList.stream()
.filter(aString -> aString.codePoints().anyMatch(Character::isDigit))
.toArray(String[]::new);
}
// Another method to make this list implementation distinct from ArrayList for
// the sake of this StackOverflow question example
public String[] getUpperCaseContaining()
{
return this._myStringList.stream()
.filter(aString -> aString.codePoints().anyMatch(Character::isUpperCase))
.toArray(String[]::new);
}
}
这种设计是否具有一个内部抽象集合对象作为该对象继承(继承)的类的支持对象(组成),这被认为是利用java.util包中定义的各种抽象集合类的“正确”方式?
解决方法
您正在不必要地组合事物。如果您想拥有示例中的内容,请遵循Lino的建议:
public class MyStringList extends ArrayList<String> {
public String[] getNumericContaining() {
return this.stream()
.filter(aString -> aString.codePoints().anyMatch(Character::isDigit))
.toArray(String[]::new);
}
public String[] getUpperCaseContaining() {
return this.stream()
.filter(aString -> aString.codePoints().anyMatch(Character::isUpperCase))
.toArray(String[]::new);
}
}
您需要多少次常规List<String>
,因为您可以将额外的行为提取给封装列表的类,例如
public class MySomeService {
// This could be passed in,loaded from somewhere,etc.
private List<String> foo;
public void serviceMethod() {
doSomething();
String[] numbers = getNumericContaining();
doSomethingElse(numbers);
}
// The previous methods
private String[] getNumericContaining() {
foo.stream(). // and so on
}
这取决于您的列表本身是否真的是一个类,还是它只是您有时需要的一种特殊口味。如果是第一个,则可能值得拥有自己的类;如果是后者,则不应该拥有自己的类。
最后,即使OOP告诉您将数据和行为放在同一位置,有时还是有必要将它们放在不同的位置,因此可以使用方法或函数。只需将列表作为参数传递,它将适用于所有Collection
类,而不仅仅是您的特殊类。