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

发布于 2025-01-07 04:53:16 字数 755 浏览 3 评论 0原文

我是 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 所做的一些其他属性/方法不是。那么,LCDMonitor 的子级,对吧?

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

谢谢 :)

I'm a newcomer of OOP, so I has one silly question about when a class extends another class.

Here my example:

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

I have one question for above code : because LCD is extended from Monitor and LCD has some other properties/methods that Monitor does not. So, LCD is child of Monitor, right ?

It means you try to put a "big box" to a "small box". So, why when I return new LCD, Eclipse don't notice error as when I just use class LCD {.

Thanks :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蓝天白云 2025-01-14 04:53:16

在第二种(错误)情况下,您忘记声明 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(){           
    }       
}

Edit (回应评论): LCD 根本不是问题与 Monitor 相比,code> 类具有额外的属性/方法。将调用 getMonitor() 的代码,只关心它是否获得 Monitor 返回 - 也就是说,具有 Monitor() 的所有方法、属性和行为的东西。代码>监视器。

因此,如果您的 Monitor 类上有 turnOffdisplayBitmap(int[][] data) 方法,那么您的 LCD 类也会有这些方法。当需要时,LCD 的任何实例都可以充当 Monitor - 这是 OO 语言中子类化的基本原则。因此,每当需要 Monitor 时,您都可以给它一个 LCD,或者一个 CRTSamsungLCD 实例如果你有这些,编译器可以确信正确的方法/属性将存在并且可以被调用。

(从技术上讲,如果您喜欢正式定义,那么这就是 里氏替换原则,但您不需要如此详细地理解它。)

In your second (error) case, you've forgotten to declare that LCD does in fact extend Monitor. You're just defining a "normal", standalone class - and so a new LCD() is not an instance of Monitor.

The compiler should be happy if you declare the LCD class like this:

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

Edit (in response to comment): It's not a problem at all that the LCD class has extra properties/methods compared to Monitor. The code that's going to call getMonitor(), only really cares that it gets a Monitor back - that is, something that has all the methods and properties and behaviour of a Monitor.

So if you had turnOff and displayBitmap(int[][] data) methods on your Monitor class, then your LCD class will also have these methods. Any instance of LCD can behave as a Monitor when one is needed - this is the basic principle of subclassing in OO languages. So whenever something wants a Monitor, you can give it an LCD, or an instance of CRT or SamsungLCD instead if you had those, and the compiler can be satisfied that the right methods/properties will exist and can be called.

(Technically this is the Liskov substitution principle if you like formal definitions, but you don't need to understand it in that level of detail.)

快乐很简单 2025-01-14 04:53:16

盒子的类比是错误的,应该将其视为关系。

在第一个示例中,LCD 扩展了 Monitor,即 LCD 是一个 Monitor,因此在任何需要 Monitor 的地方,LCD 都可以。当您考虑现实世界而不是查看代码时,您会意识到这是正确的。一般情况下,您可以期望显示器执行的所有操作(例如显示图片),液晶显示器都可以执行。

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

The box analogy is wrong, think of an is a relationship instead.

In the first example, LCD extends Monitor, that is LCD is a Monitor, therefore anywhere where Monitor is expected, LCD is fine. When you think about in real-world terms instead of looking at the code, you realise this is correct. Everything that you can expect a monitor in general to do (e.g. display a picture), an LCD monitor will do.

In the second example LCD is not a Monitor, so you get an error message.

毁梦 2025-01-14 04:53:16

将继承理解为“是”关系。这是我在新手时期用来理解继承的一个简单例子。

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 没有奖金方法。
但使用演员表我们可以让它发挥作用。
((Manager)em.)getBonus()

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

Manager[] Managers = new Manager[10];

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

Employee[] Staff = Managers; // 好吧

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

现在考虑语句

Staff[0] = new Employee("John Eipe", ...);

编译器会很高兴地允许这个分配。
但是,staff[0] 和 manager[0] 是相同的引用,因此看起来我们似乎成功地将一名员工偷偷带入了管理层
行列。

这将是非常糟糕的——调用managers[0].setBonus(1000)会尝试访问
不存在的实例字段会损坏相邻的内存。
为了确保不会发生此类损坏,所有数组都会记住元素类型
它们被创建,并且它们监视仅兼容的引用被存储到
他们。例如,创建为 new Manager[10] 的数组会记住它是一个数组
经理。尝试存储 Employee 引用会导致 ArrayStoreException。

Understand Inheritance as a "is a" relationship. Here is a simple example I used to understand inheritance during my novice years.

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

Compiler looks for reference type before calling any operations on it.
em.getBonus() doesn't work because Employee doesn't have a bonus method.
But using a cast we can make it work.
((Manager)em.)getBonus()

Reason why compiler looks for the reference type before calling any operation on it is as follows:

Manager[] managers = new Manager[10];

It is legal to convert this array to an Employee[] array:

Employee[] staff = managers; // OK

Sure, why not, you may think. After all, if manager[i] is a Manager, it is also an Employee. But actually, something surprising is going on. Keep in mind that managers and staff are references to the same array.

Now consider the statement

staff[0] = new Employee("John Eipe", ...);

The compiler will cheerfully allow this assignment.
But staff[0] and manager[0] are the same reference, so it looks as if we managed to smuggle a mere employee into the management
ranks.

That would be very bad — calling managers[0].setBonus(1000) would try to access a
nonexistent instance field and would corrupt neighboring memory.
To make sure no such corruption can occur, all arrays remember the element type with
which they were created, and they monitor that only compatible references are stored into
them. For example, the array created as new Manager[10] remembers that it is an array of
managers. Attempting to store an Employee reference causes an ArrayStoreException.

仄言 2025-01-14 04:53:16

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

当您使用监视器扩展您的 LCD 类时,您是在说 LCD 是一个监视器。
当您删除扩展时,LCD 类将变为普通类,而不是监视器类型。
如果您将 getMonitor 修改为

public LCD getMonitor(){
       // code here
}

错误就会消失。

Your method getMonitor returns a "Monitor" type.

When you extend your class LCD with Monitor, you are saying the complier that LCD is a Monitor.
When you remove the extends, the LCD class becomes a plain class and not a Monitor type.
If you modify your getMonitor to

public LCD getMonitor(){
       // code here
}

The error will go.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文