OOP Java:可以将子类返回到父类吗?

OOP Java:可以将子类返回到父类吗?,java,oop,extends,Java,Oop,Extends,我是OOP的新手,所以我有一个愚蠢的问题,关于一个类何时扩展另一个类 以下是我的例子: public class Test { public Monitor getMonitor(){ return new LCD(); } class LCD extends Monitor { NO-ERROR class LCD { ERROR at line `return new LCD` //s

我是OOP的新手,所以我有一个愚蠢的问题,关于一个类何时扩展另一个类

以下是我的例子:

public class Test {
    public Monitor getMonitor(){
        return new LCD();
    }

    class LCD extends Monitor {   NO-ERROR
    class LCD {                   ERROR at line `return new LCD` 
        //some other method or function not in Monitor Class. Example:
        boolean isSamsung;
        public LCD whatkindLCD(){           
        }       
    }
}
对于上面的代码,我有一个问题:因为
LCD
是从
Monitor
扩展而来的,
LCD
还有一些Monitor没有的属性/方法。所以,
LCD
Monitor
的孩子,对吗

这意味着你试图把一个“大盒子”变成一个“小盒子”。那么,为什么当我
返回新的LCD
时,Eclipse不会注意到错误,就像我只使用
类LCD{
一样


谢谢:)

盒子类比是错误的,想想
是一种关系

在第一个例子中,
LCD扩展了监视器
,也就是说
LCD是一个监视器
,因此在任何需要监视器的地方,LCD都是好的。当你从现实世界的角度来考虑而不是看代码时,你会意识到这是正确的。你可以期望监视器一般做的一切(例如显示图片),液晶显示器就可以了

在第二个示例中,LCD不是监视器,因此您会收到一条错误消息。

在第二个(错误)案例中,您忘记声明
LCD
实际上扩展了
Monitor
。您只是定义了一个“普通”的独立类,因此
新的LCD()
不是
监视器的实例

如果您像这样声明
LCD
类,编译器应该会很高兴:

class LCD extends Monitor {
    //some other method or function not in Monitor Class. Example:
    boolean isSamsung;
    public LCD whatkindLCD(){           
    }       
}

Edit(回应评论):与
Monitor
相比,
LCD
类具有额外的属性/方法,这一点都不是问题
,只是真正关心的是它得到一个
监视器
,也就是说,它拥有
监视器
的所有方法、属性和行为

因此,如果您关闭了
显示位图(int[][]数据)
Monitor
类上的
方法,那么您的
LCD
类也将具有这些方法。
LCD
的任何实例在需要时都可以充当
监视器
——这是OO语言中子类化的基本原则。因此,每当需要
监视器
时,您都可以给它一个
LCD>,或
CRT
SamsungLCD
的实例(如果您有这些实例),编译器可以确信正确的方法/属性将存在并可以调用


(从技术上讲,如果您喜欢正式的定义,这是最好的方法,但您不需要了解它的详细程度。)

您的方法
getMonitor
返回一个“Monitor”类型

当你用显示器扩展你的类LCD时,你是在告诉编译器LCD是一个显示器。 删除扩展后,LCD类将变为普通类,而不是监视器类型。 如果将getMonitor修改为

public LCD getMonitor(){
       // code here
}

错误将会消失。

将继承理解为一种“是一种”关系。下面是一个我在新手时代用来理解继承的简单示例

class Employee
{
    String name;
    int salary;

    Employee()
    {
        name = "Employee";
        salary = 5000;
    }
    public String getName()
    {
        return name;
    }
    public int getSalary()
    {
        return salary;
    }
}
class Manager extends Employee
{
    int bonus;
    int salary;

    Manager()
    {
        bonus = 1000;
        salary = 6000;
    }
    public int getBonus()
    {
        return bonus;
    }
    public int getSalary()
    {
        return salary;
    }   
}

class Test
{        
    public static void main(String[] args)
    {
        Employee e = new Employee();
        System.out.println(e.getName());
        //System.out.println(e.getBonus());
        System.out.println(e.getSalary());

        System.out.println();

        Manager m = new Manager();
        System.out.println(m.getName());
        System.out.println(m.getBonus());
        System.out.println(m.getSalary());

        System.out.println();

        Employee em = new Manager();
        System.out.println(em.getName());                   
        //System.out.println(em.getBonus());            
        System.out.println(((Manager)em).getBonus());
        System.out.println(em.getSalary());     
        }
}
编译器在调用引用类型上的任何操作之前查找引用类型。 em.getBonus()不起作用,因为员工没有奖金方法。 但是使用石膏我们可以让它工作。 ((经理)em.)获得奖金()

编译器在调用引用类型上的任何操作之前查找该引用类型的原因如下:

经理[]经理=新经理[10]

将此数组转换为Employee[]数组是合法的:

Employee[]staff=managers;//确定

当然,你可能会想,为什么不呢?毕竟,如果经理[i]是一名经理,那么他也是一名员工。但事实上,令人惊讶的是,发生了一些事情。请记住,经理和员工是指同一个数组

现在考虑语句

员工[0]=新员工(“John Eipe”,…)

编译器将愉快地允许此赋值。 但是员工[0]和经理[0]是同一个参考,所以看起来好像我们设法将一名员工偷偷带进了管理层 排名

这将非常糟糕-调用管理器[0]。setBonus(1000)将尝试访问 实例字段不存在,将损坏相邻内存。 为了确保不会发生此类损坏,所有数组都使用 它们是创建的,并且它们监视只有兼容的引用存储到 例如,作为新管理器创建的数组[10]记住它是一个
经理。试图存储员工引用会导致ArrayStoreException。

否,请在拿回显示器时尝试强制转换。@TedHopp在Eclipse中,它会注意到:
无法从LCD转换为监视器类
是。我知道为什么
类LCD
会出错。我不知道的是:为什么可以将
LCD
指定为
监视器tor
,因为
LCD
有一些属性是
Monitor
不要的。谢谢你给我的链接。我无法想象这个简单的想法背后有一个原则。太有趣了!正如我对Doyle说的,我只是不知道:为什么可以将
LCD
指定为
Monitor
,因为
LCD
有一些属性是
监视器
不要。在正常生活中,你可以说
液晶显示器
是一个
监视器
。但我无法想象,为什么你可以使用
监视器
变量,比如
液晶显示器
变量?是的,但这些属性并不重要。如果有人要一杯水,他们通常不在乎玻璃是塑料、玻璃还是金属制成的,不管它是否有把手,或者如果它确实是一个杯子,它有什么样的装饰,如果有的话。不,唯一重要的是它可以盛水,并且可以从中喝水。这里也是一样:通过定义返回
监视器
类型的方法,你可以声明你对任何其他属性都不感兴趣可能有。啊。谢谢你。那么,你是说,什么时候