使用类和类的继承 要求:创建一个名为 Animal 的类,包含一个构造函数和一个 speak 方法。然后创建一个继承自 Animal 的 Dog 类,并重写 speak 方法来输出“Woof”。实例化一个 Dog 对象并调用 speak 方法
时间: 2024-10-26 09:03:11 浏览: 44
在面向对象编程中,类是一种蓝图,用于描述具有相似特性和行为的对象集合。首先,我们创建一个基础类 `Animal`,它有一个构造函数和一个 `speak` 方法:
```javascript
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return 'Animal makes a sound';
}
}
```
接着,我们创建一个名为 `Dog` 的子类,它继承自 `Animal`,并且覆盖了 `speak` 方法:
```javascript
class Dog extends Animal {
speak() {
return 'Woof!';
}
}
```
现在我们可以实例化一个 `Dog` 对象并调用其 `speak` 方法:
```javascript
const myDog = new Dog('Rex');
console.log(myDog.speak()); // 输出 "Woof!"
```
在这个例子中,`myDog` 是一个 `Dog` 类的实例,尽管它的父类 `Animal` 提供了一个默认的 `speak` 实现,但我们通过子类重写了它,使其特定于 `Dog`。
相关问题
作业 3:使用类和类的继承 要求:创建一个名为 Animal 的类,包含一个构造函数和一个 speak 方法。然后创建一个继承自 Animal 的 Dog 类,并重写 speak 方法来输出“Woof”。实例化一个 Dog 对象并调用 speak 方法。
在Java中,你可以按照以下步骤完成这个作业:
首先,创建一个名为`Animal`的类,它通常用于表示动物的一般特性,比如有一个构造函数来初始化对象,以及一个`speak`方法表示通用的叫声,这个方法默认返回一个空字符串。
```java
public class Animal {
// 构造函数
public Animal() {}
// 默认的speak方法
public String speak() {
return "";
}
}
```
接着,为了实现类的继承,我们创建一个名为`Dog`的类,它从`Animal`类继承而来,并覆盖`speak`方法以输出特定的声音" Woof "。
```java
public class Dog extends Animal {
@Override
public String speak() {
return "Woof";
}
}
```
现在,我们可以创建一个`Dog`对象并调用它的`speak`方法:
```java
public static void main(String[] args) {
// 实例化Dog对象
Dog myDog = new Dog();
// 调用speak方法,输出"Woof"
System.out.println(myDog.speak());
}
```
在这个例子中,`myDog`是一个`Dog`类型的对象,虽然它是通过`Animal`类创建的,但由于`speak`方法已经被重写了,所以当调用`myDog.speak()`时,会执行`Dog`类的`speak`方法,而不是`Animal`类的默认行为。
本关任务:根据给出的基类Animal和main()函数。 1、根据给出的main()函数和运行结果的提示,设计出相关的各个类,注意观察运行结果,提取出每个类中需要的数据成员,并匹配上需要的成员函数。 2、显然,Animal设计为抽象类更合适,Animal不需要能够实例化,是专门作基类使用的。改造程序,使Animal设计为抽象类,这时main()函数中p = new Animal();将出错,将此行删除。 3、每一个Animal的派生类都有一个“名字”数据成员,这一共有的成员完全可以由基类提供改造上面的程序,将这一数据成员作为抽象类Animal数据成员被各派生类使用。 下面是给出的基类Animal和main()函数:
基类Animal代码如下:
```c++
#include <iostream>
using namespace std;
class Animal{
protected:
string name;
public:
Animal(string n):name(n){}
virtual void speak() = 0;
};
```
注释:Animal类是一个抽象类,有一个纯虚函数speak(),表示动物的叫声,同时有一个string类型的name数据成员,表示动物的名字。
main()函数代码如下:
```c++
int main(){
Animal *p;
Cat c("Tom");
Dog d("Jerry");
p = &c;
p->speak();
p = &d;
p->speak();
return 0;
}
```
注释:main()函数中定义了Animal类型的指针p,通过动态绑定,p可以指向Cat类型或Dog类型的对象。同时定义了Cat类型的对象c和Dog类型的对象d,并分别将它们的地址赋值给指针p,调用speak()函数输出它们的叫声。
Cat类和Dog类的代码如下:
```c++
class Cat: public Animal{
public:
Cat(string n):Animal(n){}
void speak(){
cout << name << " Meow~" << endl;
}
};
class Dog: public Animal{
public:
Dog(string n):Animal(n){}
void speak(){
cout << name << " Woof!" << endl;
}
};
```
注释:Cat类和Dog类都是Animal类的派生类,继承了Animal类的name数据成员和speak()纯虚函数。它们分别重载了speak()函数,输出各自的叫声。同时,在构造函数中初始化name数据成员。
改造后的Animal类代码如下:
```c++
#include <iostream>
using namespace std;
class Animal{
protected:
string name;
public:
Animal(string n):name(n){}
virtual void speak() = 0;
virtual ~Animal(){} //加上虚析构函数
};
```
注释:Animal类加上了虚析构函数,使得Animal类可以作为基类使用。同时,保留了原有的数据成员和纯虚函数。
改造后的main()函数代码如下:
```c++
int main(){
// Animal *p; //删除该行
Cat c("Tom");
Dog d("Jerry");
Animal *p = &c; //修改该行,使其指向Animal类型的指针
p->speak();
p = &d;
p->speak();
return 0;
}
```
注释:由于Animal类现在是一个抽象类,不能实例化,因此将p的定义和初始化放在Cat和Dog对象的定义和初始化之后。同时,由于Cat和Dog类都是Animal类的派生类,可以通过动态绑定,将它们的地址赋值给指针p。
阅读全文