繁体   English   中英

关于Java泛型和子类

[英]About Java generics and subclasses

好的,我从来没有大量使用过泛型,并且想知道是否可以通过以下方式使用它们。

假设我有这堂课

public class ASuperClass {
    public abstract void doSomething(String arg1, Integer arg2);
}

因此,如果再扩展上述类,则将具有以下内容,其中将被迫使用String和Integer的参数列表覆盖doSomething。

public class ASubClass extends ASuperClass{
    @Override
    public void doSomething(String arg1, Integer arg2){
        some code.....
    }
}

现在,假设在我的子类中可以重写doSomething,但我的子类中需要一个额外的String arg。 因此,我想做的是以下内容:

public class ASubClass extends ASuperClass{
    @Override
    public void doSomething(String arg1, Integer arg2, String arg3){
        some code...
    }
}

上面的代码不会编译,因为我的子类没有实现在基类中定义的抽象签名。 因此,要使其编译,我当然可以这样做:

public class ASubClass extends ASuperClass{
    @Override
    public void doSomething(String arg1, Integer arg2){}

    public void doSomething(String arg1, Integer areg2, String arg3){
        here is my code......
    }
}

所以,我到底想做什么呢? 我感兴趣的是,有没有一种方法可以使用泛型作为arg来“强制”类的任何子类,以实现基本的抽象方法,而与arg列表无关。 这样就可以编译扩展ASuperClass了:

public class ASubClass extends ASuperClass{
    @Override
    public void doSomething(String arg1, Integer areg2, String arg3){
        here is my code......
    }
}

 public class AnotherSubClass extends ASuperClass{
    @Override
    public void doSomething(String arg1, Integer areg2, String arg3, Integer arg4){
        here is my code......
    }
}

那么,您能否“泛化”基类的arg列表,以便可以编译以上两个类? 像下面的东西? 我知道下面的语法是错误的,但是您可以使arg列表通用吗?

public class ASuperClass {
    public abstract void doSomething(<?>);
}

总的来说,我的想法是在人们正在扩展某些基本功能的应用程序中实现一致性。 基本上确保ASuperClass的每个子类都有一个doSomething()成员函数,以确保子类之间的一致性(尤其是方法命名),但是每个子类的arg列表可能有所不同。

希望以上内容不会太混乱。 有兴趣知道这是否可能。

public class ASuperClass 
{
    public abstract void doSomething(Object ... args);
}

public class ASubClass extends ASuperClass
{
    @Override
    public void doSomething(Object ... args)
    {
        here is my code......
    }
}  

这将允许两个调用: doSomething(str1, int1)doSomething(str1, int1, str2, int2);

方法参数是方法“签名”的一部分,用于决定覆盖。 为了使子类重写其基类中的方法,实现其抽象基类的抽象方法或实现接口方法,整个签名(包括参数类型)必须匹配。

如果您希望参数列表采用可变数量的参数,则可以使用以下语法:

public abstract void doSomething(Object ... args);

您可以在子类中使用此签名覆盖方法,并且可以根据需要传递任意数量的参数。 此设计决定的一些不幸后果是:

  • 现在,您的参数是无类型的 -在继续进行计算之前,每种方法都需要验证其参数列表,包括其类型,以及
  • 基本类型的参数需要包装在Object - 基本类型需要装箱或自动装箱。

如果定义这样的抽象方法,则意味着实现该抽象类的任何类型的对象都可以保证包含该方法。

例如,看下面的代码示例。

List<ASuperClass> list = new ArrayList<ASuperClass>();
list.add(new ASubClass());
list.add(new AnotherSubClass());

因此,我们创建了所有类型均为ASuperClass的对象列表,然后将两个对象添加到该列表中。 这些对象具有不同的类型,但是它们都共享此公共父对象。 这意味着我们可以保证它们将响应ASuperClass类型上的所有方法签名。

for(ASuperClass obj : list)
{
  obj.doSomething("parm1", 1);
}

如果让子类型确定参数列表,则可能会破坏此列表。 我们会知道有一种叫做doSomething的方法,但是对我们来说这是没有用的,因为无法知道参数应该是什么。

正如其他人所建议的那样,这样做有很简单的方法。

public abstract void doSomething(Object ... params);

虽然这是完全正确的,但我敢肯定,在他们的正确思想中没有人会建议这样做。 仅出于完整性的目的提出了此建议。

另一方面,如果您想要可变数量的相同类型的参数,则可以更安全地使用它。

public abstract void doSomething(String parm1, Integer parm2, String ... params);

在这种情况下,您将始终需要一个字符串,一个整数,然后是可变数量的字符串。 这实际上等同于执行此操作。

public abstract void doSomething(String parm1, Integer parm2, String[] params);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM