第七讲 继承与多态

1.

源码:

class Grandparent {

public Grandparent() {

System.out.println("GrandParent Created.");

}

public Grandparent(String string) {

System.out.println("GrandParent Created.String:" + string);

}

}

class Parent extends Grandparent {

public Parent() {

//super("Hello.Grandparent.");

System.out.println("Parent Created");

// super("Hello.Grandparent.");

}

}

class Child extends Parent {

public Child() {

System.out.println("Child Created");

}

}

public class TestInherits {

public static void main(String args[]) {

Child c = new Child();

}

}

运行结果:

修改之前:

修改之后:

在java语言的继承中,在执行子类的构造方法之前,会先调用父类没有参数的构造方法,其目的是为了要帮助继承自父类的成员做初始化操作。子类的构造方法通过super()来调用父类特定的构造方法(如果没有super语句还是会自动调用父类没有参数的构造方法),调用父类特定的构造方法的super语句必须写在子类构造方法的第一行,否则编译时出错,如果父类只定义了有参数的构造方法,而在子类中又没有用super关键字来调用父类的特定构造方法,则编译时出错。

又问:

子类是通过父类继承过来的,所以子类有父类的所有非私有的属性和方法,如果不调用父类的构造方法,那么不能初始化父类中定义的属性,就给父类的属性分配内存空间 ,如果父类的属性没有分配内存空间,那么子类访问父类的属性,就会报错。

2.

自行编写代码测试以下特性(动手动脑):

在子类中,若要调用父类中被覆盖的方法,可以使用super关键字。

(1)覆盖方法的允许访问范围不能小于原方法。

(2)覆盖方法所抛出的异常不能比原方法更多。

(3)声明为final方法不允许覆盖。

例如,Object的getClass()方法不能覆盖。

(4)不能覆盖静态方法。

3.

m=d;         //编译正确,因为子类对象可以直接赋给基类变量。

d=m;        //编译错误,基类对象要赋给子类对象变量,必须执行类型转换(子类对象变量=(子类名)基类对象名;)

d=(Dog)m;   //编译正确,基类对象要赋给子类对象变量,必须执行类型转换

d=c;         //编译错误,不同子类之间不能复制

c=(Cat)m;    //m已经转换成Dog, Dog和Cat子类之间不能转换

4.

(1)运行结果:

(2)解释:

在调用的时候,对象是子类的,就调用子类的方法,对象是父类的,就调用父类的方法。父类对象访问子类成员,调用相同的函数名的函数属于子类的;父类的变量进行相关的原算,但是,如果这时父类变量指向子类对象,继续调用得方法和变量仍然是子类覆盖后的新的变量和方法的,例如如果将代码改为:

则第三个结果为:101

最后一个输出为父类强转为子类对象,调用的是子类的变量和方法输出。

(3)

父类对象可以访问子类的成员,当然只限于”覆盖”发生时,调用的时候,对象是子类的,就调用子类的方法,对象是父类的,就调用父类的方法。当然还有如下特性:

1.当子类与父类拥有一样的方法,并且让一个父类变量引用一个子类对象时,到底调用哪个方法,由对象自己的“真实”类型所决定,这就是说:对象是子类型的,它就调用子类型的方法,是父类型的,它就调用父类型的方法。这个特性实际上就是面向对象“多态”特性的具体表现。

2.如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。

3.如果子类被当作父类使用,则通过子类访问的字段是父类的.

5.

源码:

class Parent

{

public int value=100;

public void Introduce()
{

System.out.println("I‘m father");

}

}

class Son extends Parent
{

public int value=101;

public void Introduce()
{

System.out.println("I‘m son");

}

}

class Daughter extends Parent
{

public int value=102;
public void Introduce()
{

System.out.println("I‘m daughter");

}

}

public class TestPolymorphism
{

public static void main(String args[])
{

Parent p=new Parent();

p.Introduce();

System.out.println(p.value);

p=new Son();

p.Introduce();

System.out.println(p.value);

p=new Daughter();

p.Introduce();

System.out.println(p.value);

}

}

结果:

多态依赖于类型和实现的分离,多用来把接口和实现分离。

6.(多态:多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。)

运行结果如:

虽然猴子和鸽子有数量的变化,定义固定长度的数组使用不方便,长度有限。

(接口)固定数组实现

public class Denglu
{
public static void main(String args[])
{
Feeder f = new Feeder("小李");
// 饲养员小李喂养一只狮子
f.eat();
// 饲养员小李喂养十只猴子
for (int i = 0; i < 10; i++)
{
f.eat1();
}
// 饲养员小李喂养5只鸽子
for (int i = 0; i < 5; i++)
{
f.eat3();
}
}
}
interface Lion
{
abstract void eat();
}
interface Monkey
{
abstract void eat1() ;
}
interface Pigeon extends Lion,Monkey
{
abstract void eat3() ;
}

class Feeder implements Pigeon
{
public String name;
public Feeder(String name)
{
this.name = name;
}
public void eat()
{
System.out.println("我不吃肉谁敢吃肉!");
}
public void eat1()
{
System.out.println("我什么都吃,尤其喜欢香蕉。");
}
public void eat3()
{
System.out.println("我要减肥,所以每天只吃一点大米。");
}
}

运行结果:

时间: 2024-08-06 00:50:40

第七讲 继承与多态的相关文章

C/C++程序基础 (七)继承和多态

多态 编译时多态:重载 运行时多态:虚函数.根据运行时的类别获取正确的虚指针,从而定位正确的虚函数. 虚函数 虚函数指针:指向虚函数表.多重继承则含有多个基类的虚函数指针. 虚函数表:函数指针集合.普通继承,子类沿用父类的虚函数表,可以修改基类的虚函数表. 注意:虚函数依赖虚指针,虚指针位于对象内存空间.因此,多态在构造函数之后. 多重继承 优点:使用多个基类的接口.基类构造顺序与继承列表一致,与初始化列表无关. 问题:冗余基类导致的二义性. 解决方案:虚继承 虚继承 vitual class

第七章 继承和多态

1 继承 1.1 基类与派生类 C#中的类不支持多继承.只有在类和接口之间可以实现多继承. public static void Main() { Business c1 = new Business(); c1.Name = "李明"; c1["办公电话"] = "07188888888"; c1.Output(); ClassMate c2 = new ClassMate(); c2.Name = "张鹏"; c2.Bir

第七讲继承与接口动手实验和动手动脑

[动手实验一] 继承条件下的构造方法调用 运行 TestInherits.java示例,观察输出,注意总结父类与子类之间构造方法的调用关系修改Parent构造方法的代码,显式调用GrandParent的另一个构造函数,注意这句调用代码是否是第一句,影响重大! 结论:通过 super 调用基类构造方法,必须是子类构造方法中的第一个语句. TestInherits.java class Grandparent { public Grandparent() { System.out.println("

课堂作业05继承与多态

第七讲  继承与多态 一.为什么子类的构造方法在运行之前,必须调用父类的构造方法?能不能反过来?为什么不能反过来? 1. 由于子类是继承父类的,所以想用子类创建对象时,必须先创建父类的对象,这样子类才能有父类的属性和方法.在创建对象时如果父类的数据需要进行初始化,那么就需要调用父类的构造函数,使构造函数初始化. 2. 不能反过来 3. 原因:因为父类不知道子类有什么属性,而且反过来子类也不能得到父类初始化的变量. 二.运行以下测试代码: 1. 左边的程序运行结果是什么? 1. 你如何解释会得到这

Python学习(七)面向对象 ——继承和多态

Python 类继承和多态 在OOP(Object Oriented Programming)程序设计中,当我们定义一个class的时候,可以从某个现有的class 继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Super class). 我们先来定义一个class,名为Person,表示人,定义属性变量 name 及 sex (姓名和性别):定义一个方法:当sex是male时,print he:当sex 是female时,pr

2、C#面向对象:封装、继承、多态、String、集合、文件(上)

面向对象封装 一.面向对象概念 面向过程:面向的是完成一件事情的过程,强调的是完成这件事情的动作. 面向对象:找个对象帮你完成这件事情. 二.面向对象封装 把方法进行封装,隐藏实现细节,外部直接调用. 打包,便于管理,为了解决大型项目的维护与管理. 三.什么是类? 将相同的属性和相同方法的对象进行封装,抽象出 “类”,用来确定对象具有的属性和方法. 类.对象关系:人是类,张三是人类的对象. 类是抽象的,对象是具体的.对象可以叫做类的实例,类是不站内存的,对象才占内存. 字段是类的状态,方法是类执

Java的继承与多态

Java的继承与多态对于提高开发效率,减少开发量,是非常有帮助的,也便于代码维护.下面是根据书上讲的,我又做了改进的例子. 假设需求: 公司需要对所有人员进行管理,所有人员分为普通员工和经理人,他们的头衔.工资.生日等信息都是不一样的,但是不能开发两套系统分别进行管理,而是要一套系统完成对所有人的管理. 设计一个员工类,这是父类,定义如下: package com.myHelloWorld; import java.text.ParseException; import java.text.Si

Objective-C的封装、继承与多态

面向对象有三大特征:封装.继承和多态. 一.封装 封装是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问.简而言之,信息隐藏,隐藏对象的实现细节,不让用户看到,以此来增强安全性和简化编程,进而达到封装的目的. 使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员. 访问修饰符:private.protect.public private:私有的,不可供外部访问的信息,只有类本身能存取. prot

继承与多态

继承与多态 一.继承 子类继承父类,通过在类后面加冒号来继承某个类A:B. 继承的作用:一旦形成继承关系后,子类的对象就能够使用父类中的公共属性和方法函数 ㈠继承关系中的方法重写.虚(抽象)方法.虚(抽象)属性 ⒈重写: 当子类中重写了跟父类同名同参数的方法之后,子类创建对象后,调用的是该子类里面的同名方法. ⒉父类变量与子类变量之间转换的规则: ⑴可以定义一个父类变量,用来存储子类对象(若有函数重写,存储了子类对象的父类变量调用方法时仍访问父类的同名方法,无法调用原先子类重写的方法以及特有的方