2012-02-20 37 views
0

我是OOP的新手,所以我有一个愚蠢的问题,关于什么时候上课extendsOOP Java:可以将子类返回给父类吗?

这里我举的例子:

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(){   
     }  
    } 
} 

我对上面的代码中有一个问题:因为LCDMonitor扩展和LCD具有一些其他性能/方法监测没有。所以,LCDMonitor的孩子吧?

这意味着你试着把一个“大盒子”放到一个“小盒子”中。那么,为什么当我return new LCD,Eclipse没有注意到错误,因为当我只使用class LCD {

谢谢:)

+0

什么是错误信息? – 2012-02-20 17:12:42

+0

不,尝试投掷,当你拿回显示器。 – 2012-02-20 17:13:27

+2

@TedHopp在Eclipse中,它会注意到:'不能从LCD转换为显示器类' – hqt 2012-02-20 17:14:48

回答

1

将继承理解为“是”的关系。这里有一个简单的例子,我用它来理解我在新手年代的继承。

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()不起作用,因为Employee没有奖励方法。 但使用一个演员,我们可以使其工作。 ((经理)EM)getBonus()

之所以编译器查找引用类型调用任何操作上它是如下之前:

管理器[]管理者=新管理器[10];

是合法的这个数组转换为一个Employee []数组:

雇员[]人员=管理人员; //好的

当然,为什么不呢,你可能会想。毕竟,如果经理[我]是经理,那么他也是一名员工。但事实上,令人惊讶的事情正在发生。请记住,经理和员工都是对同一阵列的引用。

现在考虑的声明

人员[0] =新雇员( “约翰Eipe”,...);

编译器会高兴地允许这个任务。 但员工[0]和经理[0]是相同的参考,所以看起来我们设法将仅仅一名员工偷运到管理层 的行列中。

这将是非常糟糕的 - 调用管理器[0] .setBonus(1000)将尝试访问不存在的实例字段并会破坏邻近的内存。 为了确保不会发生此类损坏,所有阵列都记住它们创建时的元素类型 ,并且它们监视只有兼容的引用存储在它们中的 。例如,作为新Manager [10]创建的阵列会记住它是一个由 管理器组成的数组。尝试存储Employee参考会导致ArrayStoreException。

+1

非常清晰的例子和解释。正如你所说的那样:在新手年期间:D因此,作为例子,我明白:当你给别人打电话是一名雇员时(但实际上是一名经理),编译器会阻止你将雇员当作经理,除非你'typecast':“这名员工必须是经理,对:D – hqt 2012-02-21 06:52:37

3

盒类比是错误的,想到的is a关系来代替。

在第一个示例中,LCD extends MonitorLCD is a Monitor,因此在任何需要Monitor的地方,LCD都可以。当你用真实的术语思考而不是看代码时,你意识到这是正确的。一般你可以期待一台显示器的任何东西(例如显示一张图片),一台液晶显示器就可以。

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

+2

正如我对Doyle所说的,我只是不知道是:为什么可以将'LCD'分配为'Monitor',因为'LCD'有一些“Monitor”没有的属性。在正常的生活中,你可以说'LCD'是一个'Monitor'。但我无法想象,为什么你可以像'LCD'变量那样使用'Monitor'变量? – hqt 2012-02-20 17:19:28

+2

是的,但这些属性并不重要。如果有人要求喝一杯水,他们通常不会在意玻璃是用塑料,玻璃或金属制成的,不管它是否有手柄,或者如果是杯子,是什么样的装饰,如果有的话具有。不,唯一重要的是它可以容纳水,并且水可以从中喝掉。在这里也是如此:通过定义你的方法来返回一个'Monitor'类型,你声明你根本没有对它可能具有的任何附加属性感兴趣。 – biziclop 2012-02-20 17:22:35

+2

啊。谢谢。所以,你的意思是,当有人问:“给我一杯水”。你可以给他一个金属玻璃或塑料玻璃,对吧? – hqt 2012-02-20 17:26:14

5

在您的第二个(错误)情况下,您忘记声明LCD实际上确实延伸了Monitor。你只是定义一个“正常”,独立的类 - 所以new LCD()而不是Monitor的一个实例。

编译器应该是快乐的,如果你声明LCD类是这样的:

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

编辑(在响应评论):这不是一个问题,在所有的LCD类有额外属性/方法相比Monitor。代码将被称为getMonitor(),只是真的关心它得到了Monitor回来 - 也就是说,它具有Monitor的所有方法和属性以及行为。

所以,如果你对你的MonitorturnOffdisplayBitmap(int[][] data)方法,那么你的LCD类也将有这些方法。当需要时,LCD的任何实例都可以表现为Monitor - 这是OO语言中子类化的基本原理。因此,无论何时需要某个Monitor,您可以给它一个LCDCRTSamsungLCD的实例,而如果您有这些,并且编译器可以确信正确的方法/属性将存在并且可以被调用。

(从技术上讲这是Liskov substitution principle如果你喜欢正式的定义,但你并不需要了解它的详细程度。)

+2

是的。我知道为什么'class LCD'会出错。我不知道的是:为什么可以将'LCD'分配为'Monitor',因为'LCD'有一些属性,'Monitor'不是 – hqt 2012-02-20 17:17:47

+3

哦。感谢您的链接给我。我无法想象这种简单的想法背后有一个原则。太有趣了 ! – hqt 2012-02-21 14:42:17

0

你的方法getMonitor返回“监控”型。

当您使用显示器扩展您的班级LCD时,您所说的编译器即LCD 显示器。 当您删除扩展时,LCD类变成普通类而不是监视器类型。 如果您将getMonitor修改为

public LCD getMonitor(){ 
     // code here 
} 

错误会消失。

相关问题