Java基础自学笔记——第十三章:抽象类和接口

第十三章:抽象类和接口

一.抽象类

父类中定义了子类的共同行为

接口定义了类的共同行为(包括非相关类的)

注意:

  • 抽象类不可以创建对象,可以包含抽象方法,这些方法在具体的子类中实现
abstract class GeometircObject {
    //成员变量
	private String color;
	private boolean filled;
	//构造方法只能被子类访问,所以用protected修饰
	protected GeometircObject (){}
    //访问器getters&修改器setters
	public boolean isFilled() {
		return filled;
	}

	public void setFilled(boolean filled) {
		this.filled = filled;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public String getColor() {
		return color;
	}

	// 抽象方法,只有定义没有实现,需要被子类实现
	abstract double getArea();

	// 普通方法
	double devideArea() {
		return getArea() / 2;
	}
}
  • 抽象方法只有定义没有实现,在具体的子类中实现,一个包含抽象方法的类必须声明为抽象类
  • 抽象类的构造方法定义为protected,因为它只能被子类调用

1.抽象类与子类总结

  • 在抽象类扩展的非抽象子类中,所有的抽象方法都要被实现,抽象方法都是非静态的
  • 抽象类不能使用new操作符来初始化
  • 包含抽象方法的类必须是抽象的,但是可以定义一个不包含抽象方法的抽象类
abstract class GeometircObject {
	//不包含抽象方法的抽象类
	
	double devideArea() {
		return 2;
	}
}
  • 子类可以覆盖父类的方法,并将它定义为abstract,这种情况下子类也必须是abstract
abstract class GeometircObject {
    // 抽象方法,需要被子类实现
	abstract double getArea();
    abstract double getPrimeter();
}

abstract class Rectangle extends GeometircObject {
	private double width;
	private double height;
	public Rectangle(double width,double height) {
		this.width=width;
		this.height=height;
	}
    //只实现了getArea方法,但是没有实现getPrimeter方法,所以用abstract修饰
  	public double getArea() {
		return width*height;
	}
}

class RectangleChild extends Rectangle {
    //如果父类只有含参构造方法,那子类必须要实现,否则构造不出父类,也就构造不出自己了,除非父类有一个或默认为无参构造
	private double width;
	private double height;
	public RectangleChild(double width,double height) {
		super(width,height);
	}
    //实现父类没有实现的getPrimeter方法
	public double getPrimeter() {
		return (width+height)*2;
	} 
}
  • 即使父类是具体的,子类也可以是抽象的
  • 不能使用new操作符创建一个对象,但是可以将抽象类当做一种数据类型
  • abstract修饰符就是要求子类(覆盖)这个方法,调用可以以多态的方式调用子类覆盖后的方法
	public static void main(String[] args) {
		//abstract修饰的getArea()由Circle子类实现,可以使用多态动态调用子类覆盖后的方法
		GeometircObject circle = new Circle(3);
		System.out.println(circle.getArea());
	}

二.抽象的Numer类

Number是抽象包装类,是BigInteger和BigDecimal的抽象父类

//byteValue和shortValue由inValue()方法得来,所以它不是抽象方法
byte byteValue(){
return (byte)intValue();
}
short shortValue(){
return (short)intValue();
}

//抽象方法
abstract int intValue();
abstract double doubleValue();
……

三.Calendar和GregorianCalendar

GregorianCalendar是抽象类Calendar的抽象子类

GregorianCalendar和Calendar有很多方法,这里就不一一介绍了

值得一提的是Calendar类中有很多常量
例:YEAR 年
MONTH 月(0代表一月)
DAY_OF_WEEK (一周的天数,1是星期日)
……

	public static void main(String[] args) {
		// 创建GregorianCalendar实例
		Calendar calendar = new GregorianCalendar();
		// 打印当前年-月-日 备注:月份中0代表1月
		System.out.println(calendar.get(Calendar.YEAR) + "-" + calendar.get(Calendar.MONTH) + "-"
				+ calendar.get(Calendar.DAY_OF_MONTH));
	}
	//结果:2020-1-27 (实际是2020年2月27日)

四.接口

接口是一种与类相似的结构,只包含常量和抽象方法

接口的目的是指明多个相关或不相关的多个对象的共同行为

语法

修饰符 interface 接口名{
//常量声明   默认使用public static final 修饰 
public static final int NUMBER=1; //等价于int NUMBER=1;
//方法签名   默认使用public abstract 修饰
public abstract void function();//等价于void function();
}
  • 不能使用new操作符创建接口实例
  • 实现接口使用的关键字是inplements
	public static void main(String[] args) {
		//使用接口CouldCall作为引用变量的类型
		CouldCall animal = new Tiger();
		System.out.println(animal.callFunction());
	}

}

//可食用接口
interface CouldEat {
	// 烹饪方法
	public abstract String cookingFunction();
}

//叫声接口
interface CouldCall {
	// 叫声
	public abstract String callFunction();
}

//动物类
class Animal {

}

//老虎继承自动物类并且实现叫声接口,切记:老虎不能吃,禁食野味,爱自己也爱护他人!
class Tiger extends Animal implements CouldCall {
	public String callFunction() {
		return "ao";
	}
}

//鸡继承自动物类,实现叫声接口和可以食用接口
class Chicken extends Animal implements CouldCall, CouldEat {
	public String cookingFunction() {
		return "Broil";
	}

	public String callFunction() {
		return "gogogo";
	}

可以使用接口作为引用变量的数据类型或类型转换的结果

五.Comparable接口

//Comparable是一个泛型接口
interface Comparable<E>{
	//比较方法返回一个int类型值
	public int compare(E object);
}

instanceof 关键字用于判断是否是此类的实例

//判断animal是否是Animal的实例
System.out.println(animal instanceof Animal);//true

【补充 20220218】
12.Comparable接口和Compartor接口
Comparable是一个排序接口,实现这个接口代表这个类支持排序 传递一个对象和自己比,内比较器
Compartor是一个比较器,创建一个比较器比较进行排序 外比较器

六.Cloneable接口

Cloneable给出了一个可克隆的对象

正常接口应该包含常量和抽象方法,但是Cloneable接口是空的

public interface Cloneable{}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = { 3, 5, 4, 6 };
		int[] array2 = array.clone();
		// 克隆实际上是创建了一个新的对象
		System.out.println(array == array2);
		array2[2] = 2;
		printArray(array);
		printArray(array2);
	}

	public static void printArray(int[] list) {
		for (int i : list) {
			System.out.print(i + " ");
		}
		System.out.println();
	}
	//结果
   	//false
    //3 5 4 6 
    //3 5 2 6 

实现Cloneable接口

//定义Cloneable 接口
interface Cloneable {

}
//Circle类实现Cloneable 接口
class Circle extends GeometircObject implements Cloneable {
//……
	@Override
	public Object clone() throws CloneNotSupportedException {
		// 调用父类的Clone方法,会抛出一个CloneNotSupportedException的异常
		return super.clone();
	}
}

下图是clone方法在Object类中的实现,可以看到使用native修饰的,由c语言编写的,并且只能由包内类和子类可以访问
在这里插入图片描述

七.接口与抽象类的区别

一个类只能继承一个父类,但是可以实现多个接口

抽象类接口
变量无限制public static final 修饰
构造方法通过构造方法链继承构造方法,不能通过new操作符创建对象不能通过new操作符创建对象
方法无限制public abstract修饰

接口可以继承其他接口,这样的接口称为子接口

所有的类共享一个根类Object,但是接口没有共同的根,接口可以定义一种类型,一个接口变量可以引用任何实现改接口的类的实例

类名可以是名词,接口名可以是形容词和名次

强的“是一种”关系用类来描述 例如:公历是日历的一种
弱的“是一种”关系用接口来描述 例如:所有的字符串都是可比较的

注意

接口可以扩展其他的接口而不是类,一个类可以扩展它父类的同时实现多个接口
【补充 20220218】
共同点:
都不能new对象
继承抽象类或 实现接口的类必须实现他们的抽象方法,否则需要定义为抽象类
抽象方法都没有方法体,只能由子类来实现
都描述是一种的关系,强的是一种用抽象类,若的是一种用接口
不同点:
抽象类定义了子类的共同行为
接口定义了类的共同行为,包括非相关类的
抽象类中可以有抽象方法和其它方法,接口中只能有抽象方法,静态方法和默认方法
抽象类中可以有变量和常量,接口中只能有静态常量
抽象类可以实现接口,接口不能实现接口
抽象类不可以多继承,可以多实现接口,但是接口可以多继承接口

八.Rational类

Rational类用于处理有理数,具体的方法就不一一描述了

Rational类没有提供分子、分母的set方法,也就是说值不可改变,像String和基本数值类型的包装类一样

Rational类有严格的限制,容易溢出,可以使用BigInteger表示分子和分母

九.类的设计原则

  • 内聚性 各司其职,内聚到一个
  • 一致性 名字和方法一致性
  • 封装性 保护和维护私有数据
  • 清晰性 方法设计,数据导入
  • 完整性 提供多种方案实现不同的需求
  • 实例和静态 设为静态,类名直接调用
  • 继承和聚合 “是一种”和“具有”的关系
  • 接口和抽象类 弱“是一种”和强“是一种”的关系

每个接口都被编译成独立的字节码文件

深复制和浅复制

class Course implements Cloneable{
	public Object clone() {
		//深复制
		Course c=(Course)super.clone();
		c.student=student.clone();
        
        //浅复制
        c.student=super.clone();
	}
}

十.总结

通过对本章的学习,我大致学会了使用抽象类和接口,以及他们使用的场景和规则,还学会了 几个具有代表性的类,掌握了接口和抽象类的区别,最后,懂得了类的设计原则。

加油!第十四章待更……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值