美好的一天!
我正在审查Java OO概念。 并编写了以下代码:
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.eat();
dog.sleep();
}
}
abstract public class Animal {
private int age;
public Animal (){
age = 1;
}
public Animal (int age){ //How can I call this constructor?
this.age = age;
}
public void eat(){
System.out.println("Eat");
}
abstract public void sleep();
}
abstract public class Canine extends Animal{
abstract public void roam();
}
public interface Pet {
public String petName = null; //i want the pets to have a variable petName.
public void trick();
}
public class Dog extends Canine implements Pet{
public void roam(){
System.out.println("roam");
};
public void sleep(){
System.out.println("sleep");
};
public void eat(){
System.out.println("Eat Dog");
};
public void trick(){
System.out.println("trick");
}
}
我有几个问题如下:
如何调用Animal Overloaded构造函数?
如何在PET界面中使用变量petName?
我是否正确地做了OO的概念?我违反了什么规则?
提前谢谢。
答案 0 :(得分:3)
一些解决方案:
public interface Pet {
String getName();
void trick();
}
现在Dog类(或任何实现Pet的类)必须实现Pet.getName()。为Dog类提供一个名为'name'的String类型的字段,并从Dog.getName()返回它。
public abstract class Canine extends Animal {
public Canine(int age) {
super(age); // pass the age parameter up to Animal
}
...
}
public class Dog extends Canine implements Pet {
private final String name;
public Dog(String name,int age) {
super(age); // call the age constructor
this.name=name;
}
public String getName() { return name; }
... rest of class ...
}
每个子类(尤其是抽象的子类)都需要为要调用的所有父类构造函数提供匹配的构造函数! (所以我将年龄参数添加到Canine构造函数中,以便Dog可以将年龄参数传递给它。
答案 1 :(得分:2)
答案 2 :(得分:1)
1)你可以将争论的构造函数称为“this(20);”
显式构造函数调用的示例
公共课点{
int mx;
int my;
//============ Constructor
public Point(int x, int y) {
mx = x;
my = y;
}
//============ Parameterless default constructor
public Point() {
this(0, 0); // Calls other constructor.
}
. . .
} super(...) - 超类(父)构造函数 对象具有自己的类的字段以及其父类的所有字段,祖父类,一直到根类Object。有必要初始化所有字段,因此必须调用所有构造函数! Java编译器会在构造函数链接过程中自动插入必要的构造函数调用,或者您可以显式地执行此操作。
如果没有构造函数调用作为构造函数的第一个语句,Java编译器会插入对父构造函数(super)的调用。以下是上面的构造函数的等价物。
//============ Constructor (same as in above example)
public Point(int x, int y) {
super(); // Automatically done if you don't call constructor here.
m_x = x;
m_y = y;
}Why you might want to call super explicitly
通常,您不需要为父类调用构造函数,因为它是自动生成的,但有两种情况需要这样做。
您想调用具有参数的父构造函数(自动生成的超级构造函数调用没有参数)。 没有无参数的父构造函数,因为只有父类中定义了带参数的构造函数。
答案 3 :(得分:1)
调用任一构造函数都会调用重载的构造函数:两个构造函数都使用相同的名称。要调用带有int的构造函数,请调用dog = new Dog(1);
。
课程Dog
实施Pet
,因此它会有一个公开字段petName
(是super.petName
吗?)。
我没有看到任何根本性的错误。
答案 4 :(得分:1)
对父构造函数的调用是super()
;在你的情况下,例如super(12);
。请注意,对构造函数(this()
或super()
)的调用必须是第一个语句。请注意,您只能上升一个级别,因此要调用Animal
中的构造函数,“ d必须将其编码为Canine
而不是Dog
。
public Dog(int age)
{
super(age); //this will invoke Canine's overloaded constructor
}
//You must now provide the overloaded constructor in Canine which invokes
//the overloaded constructor in Animal
public Canine(int age)
{
super(age); //this will invoke Animal's overloaded constructor
}
您可以访问Pet.petName
的值,以及Pet.petName
。这是因为Interface
只能有方法(隐式public
)和常量(隐式public static final
)。你可以使用this.petName
,但这是毫无意义的(并且可能令人困惑)。您无法在其他地方设置petName
的值,因为它是final
,即使您没有声明它也是如此。
但是在这种情况下,将名称声明为接口的一部分没有意义,因为它不是常量。它应该是一些抽象或具体类的一部分,以便可以按Pet
的每个实例设置它。你应该为Pet
-
public String getName();
public String setName(String name);
这些将强制实现类提供某种实现来获取和设置Pet
的名称,而不强制该名称存储在该类的内部。
答案 5 :(得分:1)
How can I call the Animal Overloaded constructor?
你需要链接它。
abstract public class Canine extends Animal{
public Canine(int age) {
super(age);
}
// ...
}
和
public class Dog extends Canine implements Pet{
public Dog(int age) {
super(age);
}
//...
}
How can I use the variable petName in the PET Interface?
Pet.petName
。如果一个类实现了这样的接口,那么该类可以引用那些没有合格类名的常量,如下所示:petName
Am I doing the concept of OO correctly? What rules am I violating?