你能覆盖一个超类的方法吗?

时间:2014-11-06 14:24:53

标签: java

更改访问修饰符

  • 从公共到私人
  • 从私人到公众

    更改throw子句

  • 更多例外

  • 少例外

    更改退货类型

  • 到子类型

  • 到超级类型

请有人解释一下。

5 个答案:

答案 0 :(得分:6)

以下是一些覆盖规则:

  • 更改访问修饰符

    您无法降低知名度

    因为由于可见性下降而无法访问子类的重载方法,因此它可能会在运行时破坏整个事物。

    假设该方法在超类中是公共的,并且在覆盖子类时已将其更改为private,但由于您具有超类的引用,因此编译器不会抱怨但在运行时它会崩溃。

  • 更改throw子句

    您无法抛出较新的已检查或更广泛的异常

    同样适用于此处,因为编译器会查找throws的超类方法但是如果在运行时子类抛出新的或更广泛的异常,那么谁负责处理应该捕获的所有新的已检查异常编译时间。

  • 更改返回类型

    仅支持Covariant return type

    注意:协变返回类型,意味着允许返回类型在与子类相同的方向上变化。

答案 1 :(得分:4)

这是一篇简洁的小文章(http://crunchify.com/java-method-overriding-examples-and-concepts-overriding-rules/),讨论了重写方法及其中的一些规则。它非常有用,你应该看看它。一些规则如下:

  

•在java中,方法只能用Subclass编写,而不能写在同一个类中。

     

•参数列表应该与参数列表完全相同   重写方法。

     

•返回类型应该是相同的或子类型   在原始重写方法中声明的返回类型   超级。

     

•访问级别不能比   覆盖方法的访问级别。例如:如果超级   方法声明为public,然后是子类中的重写方法   不能是私人的或受保护的。

     

•实例方法可以   仅当它们由子类继承时才被覆盖。

     

•一种方法   声明最终不能被覆盖。

     

•声明为static的方法不能   被覆盖但可以重新宣布。

     

•如果方法无法继承   然后它不能被覆盖。

     

•同一个包中的子类   实例的超类可以覆盖任何超类方法   没有宣布私有或最终。

     

•不同包中的子类可以   仅覆盖声明为public或protected的非final方法。

     

•一个   无论如何,重写方法都可以抛出任何uncheck异常   被重写的方法是否抛出异常。然而   重写方法不应该抛出新的或者检查的异常   比被重写方法声明的更广泛。该   重写方法可以抛出更少或更少的异常   重写方法。

     

•无法覆盖构造函数。

此外,他还是关于重写方法的官方Oracle文章:http://docs.oracle.com/javase/tutorial/java/IandI/override.html

答案 2 :(得分:2)

几乎所有这些变化都与称为Liskov Substitution PrincipleS.O.L.I.D principles之一)的内容有关。这个原则基本上说明当你与一个类型的实例交互时,你的超类/接口在这种情况下,所有子类型/实现者必须至少暴露该接口,理想情况下,通常也必须表现相同方式。

答案 3 :(得分:2)

  • 子类只能覆盖由它继承的实例方法。由于私有方法和最终方法不是继承的,因此无法覆盖它们。

  • 重写方法的返回类型应与重写的超类方法中声明的返回类型相同,或者是子类。

  • 重写方法的参数列表应与重写的超类方法的参数列表相同。这很重要,因为不同的参数列表会导致重载而不是覆盖。

  • 重写方法的访问修饰符应该与超类方法相同或更少限制。它不能更具限制性。

  • 重写方法不能抛出比重写的超类方法声明的新异常或更广泛的异常。但是,它可以抛出比超类方法更窄或更少的异常。

  • 无法覆盖静态方法。

答案 4 :(得分:2)

在替换中更改签名的经验法则是,如果对父级的有效调用不是对子级的有效调用,则不允许执行此操作。

在您描述的方案中:

  • 从公共到私有您正在从公共API中删除该方法,这肯定会破坏调用方
  • 从私人到公共由于您现在允许更多呼叫者呼叫该方法(但不允许任何以前的呼叫者)。对于可见性的任何增加(private默认为protectedpublic)都是如此。
  • 更多例外否,因为调用者需要捕获更多异常
  • 少例外由于允许调用者捕获永远不会抛出的异常
  • 到子类型 YES 是,因为子类型的每个实例也是超类型的实例。调用者返回的返回值将是预期类型的​​实例。
  • 到超级类型否,因为调用者将期望一个子类型的实例,并且您可以返回不同子类型的实例。

您可以做的其他事情包括:

  • 将参数类型更改为超类型,因为调用者传入的子类型的任何实例也是超类型的有效值。
  • 将throws声明更改为异常的子类型,因为调用者捕获超类型异常的逻辑也将处理子类型异常。