【问题标题】:While overriding method then facing issue虽然覆盖方法然后面临问题
【发布时间】:2018-12-25 05:01:17
【问题描述】:

虽然覆盖方法然后面临问题:

public interface IProduct {
    public void sendMessage(Object object);
}


@Service
public class ProductManagere implements IProduct{

    @Override
    public void sendMessage(Product product) {
        // Added logic
    }
}

但得到以下异常:

ProductManagere 类型的方法 sendMessage(Product) 必须覆盖或实现超类型方法

我不明白为什么会抛出这个异常。我希望 product 是 Object 的子类型,所以它不会抛出异常。

【问题讨论】:

    标签: java generics methods interface


    【解决方案1】:

    在 Java 中,重写不允许参数的协方差。
    只有返回类型才有可能。
    为什么 ? 因为在子类中改变方法的参数类型并不是为了覆盖一个方法,而是重载它。这不是你的意图。

    因此,要么您必须将Object 作为子类中的参数(可能不是您想要的),要么将接口设为通用接口,例如:

    public interface IProduct<T> {
        void sendMessage(T object);
    }
    

    还有子类:

    @Service
    public class ProductManagere implements IProduct<Product>{
    
        @Override
        public void sendMessage(Product product) {
            // Added logic
        }
    }
    

    【讨论】:

    • 每次我在答案中注意到“xx 差异”时,我都必须自动投票。它存在于参加编译器构建课程的人的基因中。
    • 但值得一提的是为什么它不接受协变参数类型。
    • @Andy Turner 对。已更新。
    • @davidxxx 好的,但是为什么更改参数类型会使其重载?我知道IProduct.sendMessage 说它接受任何对象,因此,为了成为 Liskov-substitutable,ProductManagere.sendMessage 也必须接受任何对象;但是将其参数类型更改为 Product 意味着它无法处理任何不是 Product(或 null)的内容。
    • @Andy Turner 当然有道理。
    【解决方案2】:

    这在 Java 中是不允许的。你必须使用泛型。

    public interface IProduct<T> {
        public void sendMessage(T object);
    }
    

    还有服务:

    @Service
    public class ProductManagere implements IProduct<Product> {
    
        @Override
        public void sendMessage(Product product) {
            // Added logic
        }
    }
    

    或者,更改接口中的方法以匹配Product

    public void sendMessage(Product object);
    

    【讨论】:

      【解决方案3】:

      如果你的假设是正确的,那么在以下情况下会发生什么:

      IProduct prod = new ProductManager();
      prod.sendMessage("String is a subclass of Object too");
      

      使界面通用,它会正常工作。

      【讨论】:

        【解决方案4】:

        必须完全一样,因为LSP是可以破解的。但是,您可以使用泛型对类型保护做同样的事情。

        【讨论】:

        • 它们不必完全相同:如果 Java 被设计为允许逆变参数类型,则可以保留 LSP。然而,事实并非如此,因为参数类型在解决方法重载方面很重要。
        猜你喜欢
        • 1970-01-01
        • 2015-01-23
        • 1970-01-01
        • 1970-01-01
        • 2019-03-19
        • 1970-01-01
        • 2011-08-21
        • 2020-09-01
        • 1970-01-01
        相关资源
        最近更新 更多