Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我是否需要在这里使用超类构造函数调用?_Java_Oop_Inheritance_Constructor - Fatal编程技术网

Java 我是否需要在这里使用超类构造函数调用?

Java 我是否需要在这里使用超类构造函数调用?,java,oop,inheritance,constructor,Java,Oop,Inheritance,Constructor,我对Java相当陌生,仍然在练习面向对象设计和编程的基础知识。关于继承、对象创建和超级调用的正确用法,我有一些问题 请考虑以下事项: 超类 package pet public class Dog { private String foodDogEats; public Dog() { this.foodDogEats; } public String getDogFood() { return foodDogEats;

我对Java相当陌生,仍然在练习面向对象设计和编程的基础知识。关于继承、对象创建和超级调用的正确用法,我有一些问题

请考虑以下事项:

超类

package pet

public class Dog {

    private String foodDogEats;

    public Dog() {
        this.foodDogEats;
    }

    public String getDogFood() {
        return foodDogEats;
    }

    public void setDogFood() {
        foodDogEats = "kibble";
    }

}
子类

package pet

public class Fido extends Dog {

    public Fido() {
        super();
        Dog dog = New Dog();
        this.whatDoesFidoEat();
    }

    public whatDoesFidoEat(Dog dog) {
        System.out.println("Fido eats " + dog.getDogFood());
    }

}
和控制器

package pet

public class MyDogFido {

    public void MyDogFido() {
        Fido fido = new Fido();
    }

}
本例中的对象是实例化一个新的Fido对象,并在此过程中执行whatDoesFidoEat中的打印行为。我有几个问题-

因为我已经调用了一个新的Fido对象,它是Dog的扩展,如果我正确地继承了它的方法和变量,那么在Fido构造函数中实例化一个新的Dog对象是多余的吗

使用超级计算机怎么样

哪一种行为是正确的-在Fido中实例化Dog对象、调用super,或者两者都是

我最初在控制类中使用这两者编写了一些类似的代码。在写了这个问题之后,我的直觉告诉我,我应该只给super打电话

请随意评论我的示例代码,特别是this.foodDogEats;狗构造器中的行-也不确定那里的用法

谢谢

你说得对,狗=新狗;线路是多余的。它将创建第二个完全独立的狗对象


超级呼叫也是不必要的。所有Java构造函数都隐式地调用super,除非您通过调用不同的super构造函数来重写该行为。

您的代码应该在超类中显示编译器错误

让我们来看看你的逻辑:

在你的超级班级里

this.foodDogEats; // should be a compiler error
你认为它有什么作用?它什么也不做,因为它只是一个声明。“this”关键字仅表示您正在引用您创建的对象的特定实例中的变量,但您对该变量不做任何操作,从而导致错误

在子类中,您不需要调用super,因为super在默认情况下是自动调用的,除非在super类中没有无参数构造函数。

您对super的使用是正确的。 您完全不需要使用狗对象

通过扩展Dog,Fido继承了Dog的非私有字段和方法。因此,您可以简化Fido:

然后,简化您的it使用:

package pet;

public class MyDogFido {

    public void MyDogFido() {
        Fido fido = new Fido();
        //This is a setter method for your foodDogEats. It should be declared in Dog.
        fido.setFoodDogEats("Beggin' Strips");
        fido.whatDoesFidoEat();
    }

}
您仍然可以让您的Fido构造函数调用whatDoesFidoEat,但是由于对象的创建似乎并不依赖于方法,因此我发现在构造函数中避免这样的调用是更好的做法

编辑:

如果要在构造时定义foodDogEats,可以定义构造函数FidoString:


或者,如果您的FoodGoAts依赖于类而不是实例,并且从不更改,则可以使变量public static final FOOD_DOG_EATS。小心-通过Fido.FOOD\u DOG\u EATS访问它将不同于DOG.FOOD\u DOG\u EATS,因为静态变量不是继承的。

如果构造函数没有显式调用超类构造函数,那么Java编译器会自动插入对超类的无参数构造函数的调用。如果超类没有无参数构造函数,则会出现编译时错误。对象确实有这样的构造函数,所以如果对象是唯一的超类,就没有问题了

因为我已经调用了一个新的Fido对象,它是Dog的扩展,如果我正确地继承了它的方法和变量,那么在Fido构造函数中实例化一个新的Dog对象是多余的吗

它本身并不是多余的,但它是毫无意义和浪费的。您正在实例化一条新的、不同的狗,然后忽略它。垃圾收集器最终会将其清理干净,但您从一开始就不需要它。您可以在类构造函数和方法中引用的Fido是一只狗。您不需要在构造函数中执行任何操作来实现这一点,也不能在构造函数中执行任何操作来阻止它实现这一点

使用超级计算机怎么样

如果一个类的构造函数没有显式地调用同一个类的另一个构造函数或一个超类的构造函数,那么它会隐式地调用super。在这种情况下,如果超类没有这样的空构造函数,那么这是一个错误。显式调用super并不完全是多余的,因为它会抑制隐式调用,但不必这样做

哪一种行为是正确的-在Fido中实例化Dog对象、调用super,或者两者都是

通过直接或间接调用其构造函数之一初始化超类。如果超类具有空构造函数,并且您希望调用空构造函数,则该调用可以是隐式的

请随意评论我的示例代码,特别是this.foodDogEats;狗构造器中的行-也不确定那里的用法

你引用的行是错误的。如果允许的话 ,我希望它的计算结果为this.foodDogEats null的默认值,没有其他影响。那是毫无意义的

另外,你的setDogFood方法很奇怪。属性设置器通常具有以下形式:

    public void setDogFood(String what) {
        foodDogEats = what;
    }

您的原始版本有点毫无意义。

谢谢您的澄清!当我在另一个类中创建了该类的新对象,并且希望引用该特定变量时,我认为只需要担心如何使用它?只有在使用继承和变量时,才需要使用“this”关键字,类中也存在于超类中的对象或方法,这意味着它们具有相同的名称。“this”关键字让运行时知道您的意思是使用在子类中定义的实例,而不是在超类中定义的实例。否则,当使用相同的名称时会发生冲突。在这种情况下,是否应该在子类构造函数中使用该名称?在这种特定情况下,您的子类中也不需要“this”,因为据我所知,您没有任何名称冲突,但如果您确实存在此类冲突,然后您应该使用itOne注意的是,如果超类使用私有数据成员,则只能使用超类的get/set方法访问它们。您可以使用protected来允许子机箱通过此命令直接访问数据成员。通常在超类的适当功能所需的get/set方法中发生某些逻辑的情况下仍然使用private。这与问题并不完全相关,但最好避免像在Fido构造函数中那样从构造函数调用非final方法。如果您将Fido子类化并覆盖getDogFood方法,您可能会出现一些非常意外的行为。感谢您的澄清!所以基本上两者都不是——当我创建一个Fido对象时,它为我做了一切?那个么超类变量的设置呢?我需要调用超类setter方法吗?如果在超类构造函数中调用它,我可以跳过它吗?如果是这样,这样做是可以接受的做法吗?如果超类有私有变量,它必须自己设置它们。如果子类希望在构造时设置这些值,您可以将它们作为参数传递给超级构造函数。为了封装的目的,将超类中的所有变量都设置为私有是更好的做法吗?请参阅和/或感谢您的说明!一般来说,你不认为我应该在构造函数中调用setter方法吗?在这样的特定用法中,变量foodDogEats被预先确定为具有静态值,该怎么办?如果它是预先确定的并且不会更改,我是否应该麻烦使用setter而不是在构造函数中设置值,或者在类代码块中预先使用publicstaticfinal设置值呢?这是正确的,但也取决于场景。我将在编辑中详细阐述。嗯。。如果我需要一个子类来继承一个静态read:unchanging值,那么最好让超类构造函数设置这个值吗?static read:unchanging-final是不变的。静态是与类关联的东西,而不是可以读取的对象:一致?。如果选择使用静态变量,则不应在构造函数中定义它。静态最终变量应该在类级别声明时立即设置,而非最终静态变量应该由静态块设置。很抱歉造成混淆,感谢您的澄清-最终是我想在这个实例中使用的关键字。我应该在类代码块中通过声明设置关键字final的变量值吗?此外,我应该如何为这些设置关键字-公共、受保护或私有?我知道我应该在默认情况下封装并使用private,但是我想确保子类对于变量也有相同的值。感谢您的澄清!关于setDogFood——在变量是预先确定且不变的情况下,在Dog构造函数中声明该变量的值是否更好?在狗类代码块中设置它怎么样?如果我在代码块中设置了它,我应该如何在保留子类访问权限的同时正确封装它?@drs,您可以避免提供更改狗食的方法,但您不能让它真正不变,同时允许它在子类中可变。在任何情况下,您提供的方法都不会在代码中被调用;除非被调用,否则无效。如果在新实例中需要一个不同于null的值,那么构造函数的任务就是设置该值。也许您需要一个接受适当食物作为参数的构造函数。
public Fido(String foodDogEats) {
    this.foodDogEats = foodDogEats;
}
    public void setDogFood(String what) {
        foodDogEats = what;
    }