我有一系列形状(SVGShape
)并希望使用单个方法将它们添加到列表中(这将执行更多逻辑)。添加SVGCircle
的代码有效但重复。 SVGEllipse
的代码表示我想要做的事情,因此有一个方法不知道它传递了哪种类型,但无法编译。一般类型是(我认为)List<? extends SVGShape>
但这禁止添加元素(在编译时)。
我正在尝试做什么或是否需要重写?
// SVGCircle extends SVGShape
// SVGEllipse extends SVGShape
// List<SVGEllipse> ellipseList;
// List<SVGCircle> circleList;
for (SVGShape shape : shapeList) {
if (shape instanceof SVGCircle) {
SVGCircle circle = (SVGCircle) shape; // this compiles and works
circleList.add(circle);
circle.setId("circle"+circleList.size());
} else if (shape instanceof SVGEllipse) {
SVGEllipse ellipse = (SVGEllipse) shape;
addToListAndSetId(ellipseList, ellipse); // fails to compile
}
}
private void addToListAndSetId(List<SVGShape> shapeList, SVGShape shape) {
shapeList.add(shape);
// more logic here
shape.setId(shape.getLocalName().toLowerCase() + shapeList.size());
}
注意:2个答案现在已经给出了正确的方法形式。为了完整起见,修改后的调用语法为:
if (shape instanceof SVGCircle) {
addToListAndSetId(circleList, (SVGCircle) shape);
} else if (shape instanceof SVGEllipse) {
addToListAndSetId(ellipseList, (SVGEllipse) shape);
}
答案 0 :(得分:4)
如果您将方法的签名更改为void addToListAndSetId(List<? extends SVGShape>, SVGShape shape)
,则它不允许添加List
,因为没有任何内容阻止您转到方法List<SVGEllipse>
使用SVGRectangle
(您不应该将其添加到List
)。
您可以在方法中添加泛型类型参数:
private <T extends SVGShape> void addToListAndSetId(List<T> shapeList, T shape) {
shapeList.add(shape);
// more logic here
shape.setId(shape.getLocalName().toLowerCase() + shapeList.size());
}
这样,如果第一个参数是List<SVGEllipse>
,则第二个参数必须是SVGEllipse
,可以安全地添加到该列表中。
答案 1 :(得分:2)
您可能想要使用泛型。
private <T extends SVGShape> void addToListAndSetId(List<T> shapeList, T shape) {
shapeList.add(shape); // more logic here
shape.setId(shape.getLocalName().toLowerCase() + shapeList.size());
}
答案 2 :(得分:0)
编辑:在函数中强制类型匹配的更好方法是使用Eran在他的答案中提到的T extends SVGShape
,因此函数<T extends SVGShape> void addToListAndSetId2(List<T> list, T shape)
是更好的解决方案,因为不匹配的参数不会编译(根据需要):
//List<SVGEclipse> eclipses;
//SVGCircle circle;
addToListAndSetId2(eclipses, circle); // this will not compile as required
//List<SVGShape> eclipses;
//SVGCircle circle;
addToListAndSetId(eclipses, circle); // this will compile although should NOT
----编辑前:
您应该创建泛型类型的列表而不是
List<SVGCircle>, List<SVGEclipse>
使用类似List<SVGShape> or List<ISVGShape>
的通用类或接口。
以下是在编译时工作的代码段。我还根据您的问题详细信息列出了我假设的其他课程:
public static void main(String []args) {
List<SVGShape> shapes = new ArrayList<>();
// cirlce list of generic type
List<SVGShape> circleList = new ArrayList<>();
// eclipse list fof generic type
List<SVGShape> ecliplseList = new ArrayList<>();
for(SVGShape shape: shapes) {
if(shape instanceof SVGCircle) {
SVGCircle svgCircle = (SVGCircle) shape;
svgCircle.setId("some-id");
circleList.add(svgCircle);
addToListAndSetId(circleList, svgCircle);
} else if(shape instanceof SVGEcliplse){
SVGEcliplse ecliplse = (SVGEcliplse) shape;
ecliplseList.add(ecliplse);
addToListAndSetId(ecliplseList, ecliplse);
}
}
}
// This does not force both params to be of same type
public static void addToListAndSetId(List<SVGShape> shapeList, SVGShape shape) {
shapeList.add(shape);
if(shape instanceof SVGCircle) {
shape.setId("some-circle-id");
} else if(shape instanceof SVGEcliplse) {
shape.setId("some-eclipse-id");
}
}
// This DOES force both params (shapelist type and shape type) to be of same type
public <T extends SVGShape> void addToListAndSetId2(List<T> shapeList, T shape) {
shapeList.add(shape);
shape.setId("some-id");
}
public class SVGCircle extends SVGShape {
}
public class SVGEcliplse extends SVGShape {
}
public class SVGShape implements ISVGShape {
public void setId(String id) {
// some logic
}
}
public interface ISVGShape {
}