声明类名称与构造函数名称不同的Java对象

时间:2019-08-14 07:31:10

标签: java object

以下是在Java中创建对象的常用语法:

Puppy myPuppy = new Puppy( "tommy" );

根据TutorialsPoint上Java类的this description,此语法的组成部分如下:

  

声明-具有对象类型的变量名称的变量声明。

     

实例化-'new'关键字用于创建对象。

     

初始化-在'new'关键字之后是对构造函数的调用。该调用将初始化新对象。

根据this Quora article,构造函数必须与其所属的类具有相同的名称。

但是,有时我会看到在语法的构造函数部分与类名不同的地方创建了Java对象,如下所示:

Dog myDog = new Puppy( "tommy" );

我不明白上述语法如何有效。到底在做什么myPuppy是哪种类型的课程?

编辑:抱歉-为了使这一点更清楚,我在最后一行代码中翻转了Dog / Puppy引用,因为Puppy类扩展Dog类具有更大的逻辑意义。 / p>

7 个答案:

答案 0 :(得分:1)

如果Dog是Puppy的子类,或者Puppy是Interface,而Dog是其实现,则这是可能的。这是Java中多态的经典示例。

答案 1 :(得分:1)

我们在这里谈论两件事:

1)创建一个包含类定义的文件:

MyClass.java

public class MyClass {
  private int someValue;

  public MyClass(int someValue) {
    this.someValue = someValue;
  }
}

2)创建一个扩展其他类或实现接口的类:

MyInterface.java

public interface MyInterface {
  void doSomeAction();
}

MyClass.java

public class MyClass implements MyInterface {
  private int someValue;

  public MyClass(int someValue) {
    this.someValue = someValue;
  }

  public void doSomeAction() {
    // some logic here
  }  
}

在这种情况下,您可以像上面提到的那样使用代码:

MyInterface someObjectThatImplementsMyInterface = new MyClass(42);

因此,一件事是创建一个类定义,另一件事是初始化一个对象,该对象可以扩展某个类或实现某个接口。需要考虑两个不同的事情。 :)

答案 2 :(得分:1)

  

语法的构造函数部分与类名称不同

从来都不是。构造函数有一个严格的声明,其名称始终是其定义所在类的名称。

您已经看到了一个完全不同的类Dog的初始化,该类继承自Puppy

对您来说,Puppy是可爱的Dog。对我来说,Puppya little Rat。对于其他人,Puppy可能是a young Seal。但是它们都是小狗,它们都有一些共同的特征。因此,无论Puppy的实际类型如何,您都可以使用它。

不过,将Puppy作为Dog的子类是一个愚蠢的主意。 MiddleAgedDogOldDog也是如此。您可以简单地问dog.getAge(),如果它返回20,我们可以同意这个伙伴很老。

答案 3 :(得分:0)

这是由于面向对象编程中称为“继承”的概念所致。在您的示例中,您不是在创建Puppy对象,而是在创建Dog对象。 Puppy只是继承Dog的接口或类。

答案 4 :(得分:0)

  

myPuppy是哪种类型的课程?

变量 myPuppy的类型为Puppy,但是(假设此代码已编译)myPuppy所引用的对象/实例的类型为(或课程)

  

它在做什么?

这称为inheritance,即如果Dog extends Puppy,则每条狗都是小狗。因此,Puppy类型的任何字段或变量都可以引用(或“保留”)任何扩展或实现Puppy的实例。所知道的是myPuppy是一只小狗,但不是哪种小狗(假设还有Wolf extends Puppy-myPuppy可以指狗或狼)

答案 5 :(得分:0)

这是因为他们在示例中使用继承

你有

public class Puppy{...}

public class Dog extends Puppy {
    public Dog(String string) {...}
}

您现在可以在Puppy中实现Dog的接口:

public class Dog extends Puppy{...}

然后致电

Puppy myPuppy = new Dog( "tommy" );

您的小狗是狗,并且继承了父级的方法

答案 6 :(得分:0)

这称为Dynamic Binding in Java

  

动态绑定::在动态绑定中,编译器无法确定要调用的方法。覆盖是动态绑定的完美示例。在覆盖中,父类和子类都具有相同的方法。

这只是意味着何时可以在父类引用中拥有子类对象,如:

Dog myDog = new Puppy( "tommy" );

为此,您的Puppy类应该是Dog的子类

JLS 4.10.2. Subtyping among Class and Interface Types

  

鉴于非泛型类型声明C,类型C的直接超类型如下:

     

C的直接超类(第8.1.4节)。

     

C的直接超接口(第8.1.5节)。

还有4.12.2. Variables of Reference Type

  

类类型T的变量可以保存空引用或对类T或作为T的子类的任何类的实例的引用。

因此,假设您的Dog类中有bark方法,而您的小狗类中也有覆盖方法,那么

  

在编译期间,编译器不知道必须调用哪个树皮,因为编译器仅通过引用变量而不是按对象类型进行引用,因此绑定将延迟到运行时,因此将调用树皮的相应版本基于对象的类型。

相关问题