day8、9 面向对象高级特性

继承

面向对象主要特征

  • 继承(inheritance):
    • 也称泛化,继承性是子类自动共享父类属性和方法的机制,在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入自己若干新的内容
    • 继承简化了人们对事物的认识和描述,有益于软件复用,是OO技术提高软件开发效率的重要原因之一
    • 是类之间的一种关系,一般类与特殊类之间的关系
  • 封装(encapsulation):
    • 所谓封装是把对象的属性和行为结合在一个独立的系统单位内部
    • 尽可能隐蔽对象的内部细节,只向外部提供接口
    • 封装的重要意义:
      • 使对象能够集中而完整地描述并对应一个具体事物
      • 体现了事物的相对独立性,使对象外部不能随意存取对象的内部数据
  • 多态(polymorphism):
    • 指同一个命名可具有不同的语义
    • OO方法中,常指在一般类中定义的属性或方法被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为

继承的含义

  • 在Java中定义一个类时,让该类通过关键字extends继承一个已有的类,这就是类的继承(泛化)。
  • 被继承的类称为父类(超类,基类),新的类称为子类(派生类)。
  • 子类继承父类的所有属性和方法,同时也可以增加自己的属性和方法。

继承的语法

[修饰符] class 子类名 extends 父类名

例如
在这里插入图片描述

继承的规则

  • Java中只支持单继承,也就是说每个类只能有 一个父类,不允许有多重继承
  • 一个父类可以有多个子类
  • 子类继承父类所有的属性和方法

类的继承

  • 子类实例化的过程子类实例化时先实例化其父类,然后实例化子类。
  • 要先调用父类的构造器,父类构造器运行完毕,才调用子类的构造器。
  • 例如实例化类D,A->C->D。
    在这里插入图片描述
  • 子类实例化的过程
    • 使用默认的构造器
    • 在子类中的创建构造器
    • 在子类中创建构造器时,必须调用父类的构造器
      • 子类可以在自己的构造器中使用super关键字来调用父类的构造器
super (参数1,参数2,…);
* 如果使用super关键字调用父类构造器,必须写在该子类构造器的第一行
* 如调用的是父类中无参的构造器,则可以不写super( )
* 如果子类中调用了父类无参的构造器,而父类中没有无参构造器则系统编译出错

调用构造方法

在构造方法中,可以使用this或super调用其他的构造方法

  • super()
    • 作用:调用父类的构造器
    • 只能出现在子类的构造器中,且必须是第一行
    • super()中的参数,决定了调用父类哪个构造器
    • 如果子类构造器中没有出现super,那么编译器会默认加上super(),即调用父类的空构造器,如果父类没有空构造器,编译器提示错误。
  • this()
    • 作用:调用本类的构造器
    • 只能写在构造器的第一行
  • 在同一个构造器中super()和this()不能同时出现

抽象类和接口

方法覆盖

还可以称为重写(rewrite),是对从父类中继承来的方法进行改造,只有在子类继承父类时发生。

方法覆盖的规则

在子类中的覆盖方法与父类中被覆盖的方法应具有

  • 相同的方法名
  • 相同的参数列表(参数数量、参数类型、参数顺序都要相同)
  • 相同的返回值类型
  • 子类覆盖方法的访问权限要不小于父类中被覆盖方法的访问权限

在重写方法上,可以使用@Override注解来标明是重写方法
@Override表示重写(也可以省略):编译器验证@Override下面的方法名是否是父类中所有的,如果没有则报错。

Final关键字

final关键字

  • final可以修饰的元素:
    • 类:不能被继承
    • 变量(属性和局部变量):不能被重新赋值
      在声明时赋值,或在构造器中赋值
      系统不会对final属性默认的赋初始值
    • 方法:不能在子类中被覆盖,即不能修改。

抽象类

在Java中使用abstract关键字定义抽象类

  • 抽象类声明格式
[访问权限修饰符] abstract class 类名 {
……
}

抽象类是抽象方法和非抽象方法的集合,包含特殊情况如下:

  • 抽象类中可以全部是抽象方法
  • 抽象类中可以全部为非抽象方法

抽象类的规则

  • 抽象类不能被实例化;
  • 包含的抽象方法必须在其子类中被实现,否则子类只能声明为abstract;
  • 抽象方法不能为static;

在下列情况下,一个类必须声明为抽象类:

  • 当一个类的一个或多个方法是抽象方法时;
  • 当类是一个抽象类的子类,并且没有实现父类的所有抽象方法,即只实现部分;
  • 当一个类实现一个接口,并且不能为全部抽象方法都提供实现时;

接口(interface)

接口的意义
Java继承时一个类只有一个直接父类,也就是单继承,但是一个类可以实现多个接口,接口弥补了类的不能多继承缺点,继承和接口的双重设计既保持了类的数据安全也变相实现了多继承。
接口的概念
接口中只包含常量和抽象方法,而没有变量和方法的实现接口对类来说是一套规范,是一套行为协议;接口不是一个类,不能实例化
语法格式
接口的成员:抽象方法
注意
接口不是一个类,没有构造器,不能被实例化
接口使用interface关键字来定义,而不是class
接口 默认
抽象方法: public abstract

类和接口的关系

类实现接口 — implements

  • 为了使用一个接口,你要编写实现接口的类
  • 如果一个类要实现一个接口,那么这个类就必须实现接口中所有抽象方法。否则这个类只能声明为抽象类
  • 多个无关的类可以实现一个接口,一个类可以实现多个无关的接口
  • 一个类可以在继承一个父类的同时,实现一个或多个接口
[修饰符] class 类名 extends 类名 implements 接口1,接口2{
类的成员
}

多态

向上转型(Upcasting)— 子类转换为父类,自动转换;

  • 前提 — 具有继承或实现关系
  • 向上转换损失了子类新扩展的属性和方法,仅可以使用从父类中继承的属性和方法
    向上转型
    示例:
Cat a = new Cat( );
Animal c = a;
	// 引用类型向上转型
	// 子类对象赋值给父类变量
	// 实现类对象赋值给接口变量
	// 向上转型之后只能调用父类定义的方法 或 接口定义的方法

简单来说,多态是具有表现多种形态的能力的特征
同一个实现接口,使用不同的实现类而执行不同操作
多态

  • 多态(动态绑定、Polymorphism )
    • 不同的对象对同一行为作出的不同响应
    • 多态存在的三个必要条件
      • 要有继承,或实现
      • 要有重写
      • 向上转型
    • 一旦满足以上3个条件,当调用父类中被重写的方法后,运行时创建的是哪个子类的对象,就调用该子类中重写的那个方法
    • 在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际类型调用相应的方法
  • 多态的优点
    • 简化代码
    • 改善代码的组织性和可读性
    • 易于扩展

练习

1、设计2个类,要求如下:
2.1 定义一个汽车类Vehicle,
2.1.1 属性包括:汽车品牌brand(String类型)、颜色color(String类型)和速度speed(int类型)。
2.1.2 提供两个构造方法。
2.1.3 为属性提供set/get方法。
2.1.4 定义一个一般方法show(),打印Vehicle属性例如黑色的奔驰速度是240
2.1.5 在main方法中创建一个品牌为“奔驰”,颜色为“黑色”,速度为240的Vehicle对象,调用show方法。
2.2 定义一个Vehicle类的子类轿车类Car,要求如下:
2.2.1 轿车有自己的属性载人数loader(int 类型)。
2.2.2 提供该类初始化属性的构造方法。
2.2.3 重写show(),打印Car属性例如红色的本田速度是240载人数是5
2.2.4 在main方法中创建一个品牌为“本田”,颜色为“红色”,速度为240,载人数为5 Car对象,调用show方法。

package com.tech.javase.ch7.练习1;

public class Vehicle {
	// 属性
	private String brand;
	private String color;
	private int speed;
	// 构造方法
	public Vehicle(String brand, String color, int speed) {
		super();
		this.brand = brand;
		this.color = color;
		this.speed = speed;
	}
	public Vehicle() {
		super();
	}
	// set get
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public int getSpeed() {
		return speed;
	}
	public void setSpeed(int speed) {
		this.speed = speed;
	}
	// 其他方法
	public void show() {
		System.out.println("汽车品牌是"+getBrand());
		System.out.println("汽车颜色是"+getColor());
		System.out.println("汽车速度是"+getSpeed());
	}	
}
package com.tech.javase.ch7.练习1;

public class Car extends Vehicle {
	// 属性
	private int loader;
	// 构造方法
	public Car(String brand, String color, int speed, int loader) {
		super(brand, color, speed);
		this.loader = loader;
	}
	public Car() {
		super();
	}
	// set get
	public int getLoader() {
		return loader;
	}
	public void setLoader(int loader) {
		this.loader = loader;
	}
	@Override
	public void show() {
		System.out.println("汽车品牌是"+getBrand());
		System.out.println("汽车颜色是"+getColor());
		System.out.println("汽车速度是"+getSpeed());
		System.out.println("汽车载人数是"+getLoader());
	}
}
package com.tech.javase.ch7.练习1;

public class 测试 {

	public static void main(String[] args) {
		// 创建对象
		Vehicle v = new Vehicle("奔驰","黑色",240);
		v.show();
		
		Car c = new Car("本田","红色",240,5);
		c.show();
	}
}

2、设计四个类,分别如下:
3.1 设计Shape图形抽象类,颜色属性color,有两个构造方法一个showColor非抽象方法,显示图形颜色2个抽象方法,分别是:getArea计算面积、getPer计算周长、
3.2 设计 2个子类:
3.2.1 Rectangle表示矩形类,增加两个属性,Width表示长度、height表示宽度,重写getPer、getArea方法
3.2.2 Circle表示圆类,增加1个属性,radius表示半径,重写getPer、getArea方法
3.3 测试类中,在main方法中,声明创建每个子类的对象,并调用2个子类的showAll方法。

package com.tech.javase.ch7.练习2;

// 图形类
public abstract class Shape {
	// 属性
	private String colour; // 颜色
	// 构造方法
	public Shape(String colour) {
		this.colour = colour;
	}
	public Shape() {

	}
	// set get
	public String getColour() {
		return colour;
	}
	public void setColour(String colour) {
		this.colour = colour;
	}
	// 其他方法
	// 打印颜色
	public void printColour() {
		System.out.println("颜色是"+colour);
	}
	// 计算面积----抽象方法
	public abstract double getArea();
	// 抽象类 必须定义两类方法
	// 抽象的 让子类继承之后必须重写
	// 非抽象的 让子类继承之后直接使用
}
package com.tech.javase.ch7.练习2;

// 矩形类 子类 继承 抽象类 图形
public class Rectangle extends Shape {
	// 属性
	private double length;
	private double width;
	// 构造方法
	public Rectangle(String colour, double length, double width) {
		super(colour);
		this.length = length;
		this.width = width;
	}
	public Rectangle() {

	}
	// set get
	public double getLength() {
		return length;
	}
	public void setLength(double length) {
		this.length = length;
	}
	public double getWidth() {
		return width;
	}
	public void setWidth(double width) {
		this.width = width;
	}
	@Override
	public double getArea() {
		return (length+width)*2;
	}
}
package com.tech.javase.ch7.练习2;

public class Cirle extends Shape{
	// 属性
	private double r; // 半径
	// 构造方法
	public Cirle(String colour, double r) {
		super(colour);
		this.r = r;
	}
	public Cirle() {

	}
	// get set
	public double getR() {
		return r;
	}
	public void setR(double r) {
		this.r = r;
	}
	// 其他方法 求面积
	@Override
	public double getArea() {
		return 3.14*r*r;
	}
}
package com.tech.javase.ch7.练习2;

public class 图形测试 {
	public static void main(String[] args) {
		// 创建矩形类对象测试
		Rectangle r = new Rectangle("黑色",3.3,4.4);
		r.printColour();
		r.setColour("红色");
		r.printColour();
		System.out.println("面积是"+r.getArea());
		// 创建圆型对象
		Cirle c = new Cirle("黄色",5.2);
		c.printColour();
		System.out.println("面积是"+c.getArea());
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值