Java 是否可以在超类对象上调用子类的方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/898909/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:48:45  来源:igfitidea点击:

Is it possible to call subclasses' methods on a superclass object?

javainheritancesubclasssuperclass

提问by

Animal is a superclass of Dog and Dog has a method called bark

Animal 是 Dog 的超类,Dog 有一个名为 bark 的方法

public void bark()
{
    System.out.println("woof");
}

Consider the following:

考虑以下:

Animal a = new Dog();
if (a instanceof Dog){
    a.bark();
}

What will happen?

会发生什么?

  1. the assignment isn't allowed
  2. the call to bark is allowed and "woof" is printed at run time
  3. the call to bark is allowed but nothing is printed
  4. the call to bark causes a compile time error
  5. the call to bark results in a run time error
  1. 不允许分配
  2. 允许调用 bark 并在运行时打印“woof”
  3. 允许调用 bark 但没有打印任何内容
  4. 对 bark 的调用导致编译时错误
  5. 调用 bark 导致运行时错误

I said 2 as we are checking if the object is a dog; as dog is the class with the bark method in it, if it is then we call it which will print out :s

我说 2 是因为我们正在检查对象是否是狗;因为 dog 是包含 bark 方法的类,如果是,那么我们调用它,它将打印出来:s

Is my understanding correct here?

我的理解在这里正确吗?

回答by Sam Trost

This won't compile since Animal does not have a method called bark. Think of it this way, all dogs are animals, but not all animals are dogs. All dogs bark, but not all animals bark.

这不会编译,因为 Animal 没有称为 bark 的方法。这样想,所有的狗都是动物,但并非所有的动物都是狗。所有的狗都会吠,但不是所有的动物都会吠。

回答by simon622

no - the answer is;

不 - 答案是;

4) the call to bark causes a compile time error

4) 调用 bark 导致编译时错误

the bark method isnt defined as a method on the assigned type Animal, which will therefore result in compile time issue; this could be solved by casting;

bark 方法未定义为指定类型 Animal 上的方法,因此会导致编译时问题;这可以通过铸造解决;

((Dog)a).bark();

回答by Carl Manaster

It's 4. You can't ask a generic Animal - which is what your code says a is - to bark. Because you could just as easily have said

它是 4。你不能要求一个通用的 Animal - 这就是你的代码所说的 a 是 - 吠叫。因为你可以很容易地说

Animal a = new Cat();

and the bark line doesn't have a way to know that you didn't.

并且树皮线无法知道您没有这样做。

回答by coobird

The key is in the following line:

关键在以下行:

Animal a = new Dog();

Although a new instance of Dogwas created, its reference is by awhich is declared to be of the type Animal. Therefore, any references to amakes the new Dogbe handled as an Animal.

尽管Dog创建了一个新实例,但它的引用是由awhich 声明为类型的Animal。因此,任何对 的引用a都会new Dog作为Animal.

Therefore, unless Animalhas a barkmethod, the following line will cause a compiler error:

因此,除非Animalbark方法,否则以下行将导致编译器错误:

a.bark();

Even though ais tested to see if it is an instance of Dog, and a instanceof Dogwill actually return true, the variable ais still of is of type Animal, so the block inside the ifstatement still handles aas an Animal.

即使a经过测试以查看它是否是 的实例Dog,并且a instanceof Dog会实际返回true,但变量a仍然是 of 的类型Animal,因此if语句中的块仍然a作为Animal.

This is a feature of statically-typed languageswhere variables are assigned a type ahead of time, and checked at compile-time to see that the types match. If this code were performed on a dynamically-typed language, where the types are checked at runtime, something like the following could be allowed:

这是静态类型语言的一个特性,其中变量提前分配一个类型,并在编译时检查类型是否匹配。如果此代码是在动态类型语言上执行的,在运行时检查类型,则可能允许以下内容:

var a = new Dog();
if (a instanceof Dog)
    a.bark();

a.bark()is guaranteed only to execute when the instance is a Dog, so the call to barkwill always work. However, Java is a statically-typed language, so this type of code is not allowed.

a.bark()保证仅在实例为 a 时执行Dog,因此对 的调用bark将始终有效。但是,Java 是一种静态类型语言,因此不允许使用这种类型的代码。

回答by Bill the Lizard

In Head First Javathey use the very good analogy of a TV remote control for a referenceand your TV as the objectthat the reference points to. If your remote only has buttons (methods) for on, off, channel up and down, and volume up and down, it doesn't matter what cool features your TV has. You can still only do those few basic things from your remote. You can't mute your TV, for example, if your remote has no mute button.

Head First Java 中,他们将电视遥控器用作参考,并将您的电视用作参考指向的对象。如果您的遥控器只有用于开、关、频道调高和调低以及音量调高和调低的按钮(方法),那么您的电视具有什么酷炫功能都没有关系。您仍然只能通过遥控器执行这些基本操作。例如,如果您的遥控器没有静音按钮,则您无法将电视静音。

The Animal reference only knows about Animal methods. It doesn't matter what other methods the underlying object has, you can't access them from an Animal reference.

Animal 引用只知道 Animal 方法。不管底层对象有什么其他方法,你都不能从 Animal 引用中访问它们。

回答by OscarRyz

"I said 2 as we are checking if the object is a dog; as dog is the class with the bark method in it, if it is then we call it which will print out :s"

“我说 2,因为我们正在检查对象是否是一只狗;因为 dog 是包含 bark 方法的类,如果是,那么我们调用它,它将打印出 :s”

Your rationale is correct, but that's not the way it works.

你的理由是正确的,但这不是它的工作方式。

Java is an static typed language that means, the validity of the methods an object may respond to is verified at compile time.

Java 是一种静态类型语言,这意味着在编译时验证对象可能响应的方法的有效性。

You may think the check:

你可能认为支票:

if( a instanceof Dog ) 

Would do, but actually it doesn't. What the compiler do is check against the "interface" of the declared type ( Animal in this case ). The "interface" is composed of the methods declared on the Animal class.

会做,但实际上不会。编译器所做的是检查声明类型(在本例中为 Animal )的“接口”。“接口”由在 Animal 类上声明的方法组成。

If the bark()method is not defined in the super class Animalthe compiler says: "Hey, that won't work".

如果bark()方法没有在超类Animal 中定义,编译器会说:“嘿,那行不通”。

This is helpful, because "sometimes" we make typos while coding ( typing barck() instead for instance )

这很有帮助,因为“有时”我们在编码时会打错字(例如输入 barck() )

If the compiler doesn't not warn us about this, you would have to find it at "runtime" and not always with a clear message ( for instance javascript in IE says something like "unexpected object" )

如果编译器没有就此向我们发出警告,您将不得不在“运行时”找到它,而不是总是带有明确的消息(例如 IE 中的 javascript 会说“意外对象”之类的东西)

Still, static typed language like java allow us to force the call. In this case it is using the "cast" operator ()

尽管如此,像java这样的静态类型语言允许我们强制调用。在这种情况下,它使用“强制转换”运算符 ()

Like this

像这样

1. Animal a = new Dog();
2.  if (a instanceof Dog){
3.     Dog imADog = ( Dog ) a;
4.     imADog.bark();
5. }

In line 3 your are "casting" to a Dog type so the compiler may check if bark is a valid message.

在第 3 行中,您正在“转换”为 Dog 类型,因此编译器可以检查 bark 是否为有效消息。

This is an instruction to to compiler saying "Hey I'm the programmer here, I know what I'm doing". And the compiler, checks, Ok, dog, can receive the message bark(), proceed. Yet, if in runtime the animal is not a dog, a runtime exception will raise.

这是对编译器说“嘿,我是这里的程序员,我知道我在做什么”的指令。然后编译器,检查,好的,狗,可以收到消息 bark(),继续。然而,如果在运行时动物不是狗,则会引发运行时异常。

The cast could also be abbreviated like:

演员表也可以缩写为:

if( a instanceof Dog ) {
   ((Dog)a).bark();  
}

That will run.

那会运行。

So, the correct answer is 4:"the call to bark causes a compile time error"

因此,正确答案是4:调用 bark 会导致编译时错误

I hope this helps.

我希望这有帮助。

回答by Wedge

FYI, this is not a good design.

仅供参考,这不是一个好的设计。

Just about any time you have code of this form:

几乎任何时候你有这种形式的代码:

if (x instanceof SomeClass)
{
   x.SomeMethod();
}

you are abusing the type system. This is not the way to use classes, it's not the way to write maintainable object oriented code. It's brittle. It's convoluted. It's bad.

你在滥用类型系统。这不是使用类的方式,也不是编写可维护的面向对象代码的方式。它很脆。很复杂。这不好。

You can create template methods in a base class, but they have to call methods that exist in the base class and are overridden in sub-classes.

您可以在基类中创建模板方法,但它们必须调用基类中存在并在子类中被覆盖的方法。

回答by gayathri

If the idea is to print the subclass method from superclass object, this will work:

如果想法是从超类对象打印子类方法,这将起作用:

Instead of Animal a = new Dog(); if (a instanceof Dog){ a.bark(); }change to

而不是Animal a = new Dog(); if (a instanceof Dog){ a.bark(); }更改为

Animal a = new Dog();

if (a instanceof Dog){ 
    Dog d = (Dog) a; 
    d.bark();
}  

This casts the superclass back to subclass and prints it. although its bad design, its one way to know which child class object its pointing to dynamically.

这将超类转换回子类并打印它。虽然它的设计很糟糕,但它是知道它动态指向哪个子类对象的一种方法。

回答by WVrock

In java(only language i know) you can create an empty method and call it in super class. Then you can override it in subclass to do whatever you want. This way the super class calls its subclass' method.

在java(只有我知道的语言)中,您可以创建一个空方法并在超类中调用它。然后你可以在子类中覆盖它来做你想做的任何事情。这样超类调用其子类的方法。

public class Test {
    public static void main(String[] args){
        Snake S = new Snake();
        Dog d = new Dog();
    }
}


class Animal{ //Super Class
    public Animal(){
        bark(); //calls bark when a new animal is created
    }
    public void bark(){
        System.out.println("this animal can't bark");
    }
}



class Dog extends Animal{ //Subclass 1
    @Override
    public void bark(){
        System.out.println("Woof");
    }
}



class Snake extends Animal{//Subclass 2
    public void tss(){
    }
}

This code calls an object of Snake then calls an object of Dog. It writes this to console:

此代码调用 Snake 的对象,然后调用 Dog 的对象。它将这个写到控制台:

this animal can't bark
Woof

Snake doesn't have any bark method so super class' method is called. It writes the first line to the console. Dog has a bark method so super class calls it instead. It writes the second line to the console.

Snake 没有任何 bark 方法,因此调用了超类的方法。它将第一行写入控制台。Dog 有一个 bark 方法,所以超类会调用它。它将第二行写入控制台。