Java学习笔记13抽象类和接口_20200511

这篇博客主要介绍了Java中的抽象类和接口的概念及其使用。首先回顾了上一章的作业,涉及Person和Student类的设计。接着详细讲解了抽象类的应用场景,包括抽象类的声明和使用规则。然后介绍了接口,强调接口作为纯粹抽象类的角色,以及接口的继承。此外,还探讨了内部类的不同类型,如局部内部类、静态内部类和匿名内部类。最后,通过Frock、Shirt和Coat类的例子展示了如何使用抽象类和接口进行设计。
摘要由CSDN通过智能技术生成

第13章 抽象和类

01 作业回顾

***练习

  1. 编写一个Person类,包括属(name,age),构造器,方法say(返回自我介绍的字符串)。
    编写一个student类,继承Person类,增加id,score属性,以衣构造器,并覆盖say方法。

编写Test类,创建Peron和Student对象,调用say方法输出自我介绍。

package day11;

class Person{
	protected String name;
	protected int age;
		
	public Person() {
		super();
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public void say(){
		System.out.println("name:" + name);
		System.out.println("age:" + age);
	}	
}

class Student extends Person{
	private int id;
	private int score;
	public Student(String name,int age,int id, int score) {
		super(name,age);
		this.id = id;
		this.score = score;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}

	public void say() {
		super.say();
		System.out.println("id:" + id);
		System.out.println("score: " + score);
	}	
}


public class Day113 {
	public static void main(String[] args) {
		Person p = new Person("张三",20);
		p.say();
		
		Student s  = new Student("李四", 10, 1, 99);
		s.say();		
	}

}



/*
name:张三
age:20
name:李四
age:10
id:1
score: 99
*/

在这里插入图片描述
在这里插入图片描述

02 抽象类

2.1 示例

在这里插入图片描述
2.1.1 初步设计

package day11;

class GraphicObject {
	protected int x;
	protected int y;
	protected String color;
	
	public GraphicObject(int x, int y, String color) {
		super();
		this.x = x;
		this.y = y;
		this.color = color;
	}
	
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public void moveTo(int x,int y) {
		this.x = x;
		this.y = y;
		
	}
	public void showLocation(){
		System.out.println("x = " + x + ", y = " + y);
	}
		
	//不知道如何实现
	public void draw() {
		
	}
	
	class Circle extends GraphicObject {
		public Circle(int x, int y, String color) {
			super(x,y, color);			
		}
		public void draw() {
			System.out.println("draw a circle at[" + x + "," + y + "]");
		}
	}
	
	class Rectangle extends GraphicObject {
		public Rectangle(int x, int y, String color) {
			super(x, y, color);
		}
		
		public void draw() {
			System.out.println("draw a Rectangle at ["  + x + "," + y + "]");			
		}
	}	
}

public class Day115 {
	public static void main(String[] args) {
		Circle c = new Circle(1, 1, "红色");
		c.draw();
		
		Rectangle r = new Rectangle(2, 2, "蓝色");
		r.draw();
	}
}



/*
draw a circle at[1,1]
draw a Rectangle at[2,2]
*/

在这里插入图片描述
在这里插入图片描述
图形对象都具有某些状态(位置,线条颜色)和 行为(moveTo,draw)。
对于所有的图形,这些状态和行为中的一些是相同(位置,线条颜色,moveTo)。

draw有些特殊。每个子类的draw方法提供的功能不同。
可以在父类中提供一个draw方法,在子类中使用方法重写来完成特定的draw方法。

GraphicObject(图形)应该是抽象的,不应该有具体的对象。在这里插入图片描述

对于这种情况可以使用抽象类来实现。

2.1.2 加入抽象类思想,进行优化改进

package day11;

//有抽角方法的类必须声明为抽象类
abstract class GraphicObject {
	protected int x;
	protected int y;
	protected String color;
	
	public GraphicObject(int x, int y, String color) {
		super();
		this.x = x;
		this.y = y;
		this.color = color;
	}
	
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public void moveTo(int x,int y) {
		this.x = x;
		this.y = y;
		
	}
	public void showLocation(){
		System.out.println("x = " + x + ", y = " + y);
	}
		
	//声明为抽象的方法,因为不知道如何云实现它
	public abstract void draw(); 
	
}		
		
	 class Circle extends GraphicObject {
		public Circle(int x, int y, String color) {
			super(x,y, color);			
		}
		
		//子类必须实现父类的抽象方法,否则这个子类必须声明为抽象类
		public void draw() {
			System.out.println("draw a circle at[" + x + "," + y + "]");
		}
	}
	
	class Rectangle extends GraphicObject {
		public Rectangle(int x, int y, String color) {
			super(x, y, color);
		}		
		public void draw() {
			System.out.println("draw a Rectangle at ["  + x + "," + y + "]");			
		}
	}	


public class Day115 {
	public static void main(String[] args) {
		//编译错误,抽象类不能被实例化
//		GraphicObject g = new GraphicObject(0, 0, "黑色");
		
		Circle c = new Circle(1, 1, "红色");
		c.draw();
		
		Rectangle r = new Rectangle(2, 2, "蓝色");
		r.draw();
	}
}

在这里插入图片描述

在这里插入图片描述
2.1.3

子类必须实现父类的抽象方法,否则这个子类必须声明为抽象类
在这里插入图片描述

2.2

抽象类使用abstract关键字来声明,它可以包含抽象方法,也可以不包含抽象方法。

声明为抽象类,又不包含抽象方法,仅仅是为了避免被实例化。

抽象类不能被实例化,但是可以被继承。

如果一个类包含了抽象方法,那么它必须声明为一个抽象类。

如果一个类继承了抽象类,它通常要实现抽象类的抽象方法,如果没有,那么这个子类也必须被声明为抽象的。

抽象类天生就是用来被继承的。抽象类实现了它所有子类必须使用的通用方法。这样子类就可以直接调用。
抽象方法则留给子类根据自己的情况做不同的实现。

定义抽象方法的意义在于:给所有的子类制定一种规则,子类必须要实现抽象方法。

抽象类使用abstract关键字来声明,它可以包含抽象方法,也可以不包含抽象方法。在这里插入图片描述

03 接口

接口定义了一个类所能对外提供的功能。接口不能被实例化,只能被实现。

接口可以理解为纯粹的抽象类,接口中的所有方法都是抽象的。

接口描述了一种规则。

3.1 示例

3.1.1

package day11;

//使用关键字interface声明了一个接口
//接口描述了一种功能
interface Flyable{
	
//	public abstract void fly();
	//public abstract不是必须的,接口的方法默认就是public abstract
	void fly();	
}

//使用关键字implements来实现一个接口
class Aeroplane implements Flyable{
	//实现一个接口,必须实现接口中的所有方法,否则这个类必须声明为抽象类
	@Override
	public void fly() {
		System.out.println("飞机能飞");
	}	
}

class Bird implements Flyable {

	@Override
	public void fly() {
		System.out.println("鸟能飞");
	}	
}


public class Day117 {
	public static void main(String[] args) {
		Bird bird = new Bird();
		bird.fly();
		Aeroplane aeroplane = new Aeroplane();
		aeroplane.fly();
	}
}

在这里插入图片描述
3.1.2 使用接口类型的变量

package day11;

//使用关键字interface声明了一个接口
//接口描述了一种功能
interface Flyable{
	
//	public abstract void fly();
	//public abstract不是必须的,接口的方法默认就是public abstract
	void fly();

}

//使用关键字implements来实现一个接口
class Aeroplane implements Flyable {
	// 实现一个接口,必须实现接口中的所有方法,否则这个类必须声明为抽象类
	@Override
	public void fly() {
		System.out.println("飞机能飞");
	}
}

class Bird implements Flyable {
	@Override
	public void fly() {
		System.out.println("鸟能飞");
	}	
}

public class Day117 {
	public static void main(String[] args) {
		Bird bird = new Bird();
		bird.fly();
		Aeroplane aeroplane = new Aeroplane();
		aeroplane.fly();
		
		//使用接口类型的变量
		//Aeroplane实现了Flyable接口,因此这个对象可以被Flyable类型的变量引用
		Flyable f1 = new Aeroplane();
		f1.fly();//多态,会调用其实际引用对象的fly方法
		//Bird实现了Flyable接口,因此这个对象可以被Flyable类型的变量引用
		Flyable f2 = new Bird();
		f2.fly();//多态,会调用其实际引用对象的fly方法		
	}
}

在这里插入图片描述
3.1.3

接口中的变量总是public static final的,接口中的变量不能声明为private。

//接口中的变量总是public static final的,接口中的变量不能声明为private。
package day11;

interface ExampleInterface1 {
	//接口中的變量默认是public static final
	//一般常量用大写
	int VALUE1 = 10;
	public int VALUE2 = 20;
	public static int VALUE3 = 30;
	public static final int VALUE4 = 40;
	//接口中不允许private变量
//	private int value5 = 50;//编译错误	
}

public class Day118 {
	public static void main(String[] args) {
		System.out.println(ExampleInterface1.VALUE1);		
	}
}

在这里插入图片描述

3.2 接口的继承

package day11;

interface Interface1 {
	void method1();
}

//Interface2继承了Interface1中的所有方法声明
interface SubInterface1 extends Interface1 {
	void  method2();
}

//ctrl + 1 自动修复错误
//实现Interface1接口,必须要实现method1和method2两个方法
class Class1 implements SubInterface1 {

	@Override
	public void method1() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void method2() {
		// TODO Auto-generated method stub
		
	}
	
}

public class Day119 {
	public static void main(String[] args) {
		
	}
}

在这里插入图片描述

一个类可以实现多个接口,它必须要实现接口中的所有方法。

package day11;

interface Singer {
	void song();	
}

interface Dancer {
	void dance();
}

//一个类可以实现多个接口,它必须要实现接口中的所有方法
//可以不实现接口中的所朋方法,但是必段志明为抽象类。
class Actor implements Singer,Dancer {

	@Override
	public void dance() {
		System.out.println("dance");
	}

	@Override
	public void song() {
		System.out.println("song");
	}
	
}

public class Day120 {
	public static void main(String[] args) {
		Singer s1 = new Actor();
		s1.song();//多态,调用实际引用对象的方法
//		s1.dance();  //编译错误,变量的类型是Singer ,所以只能看到Singer中的方法
		
		//强制类型转换
		Dancer s2=(Dancer)s1;
		s2.dance();
//		s2.song(); //编译错误,变量的类型是Singer ,所以只能看到Singer中的方法
		
	}
}

在这里插入图片描述

04 内部类

4.1 可以将一个类的定义放到另外一个类的内部,这叫做内部类。

//Foo是一个外部类
class Foo {
	//Bar是一个内部类
	class Bar {
		
	}
}

4.2 例

//Foo是一个外部类
class Foo {
	private int v1;
	
	public Foo(int v1) {
		super();
		this.v1 = v1;
	}
	
	public void fooF() {
		Bar bar = new Bar();
		bar.barF();
	}

	//Bar是一个内部类
	class Bar {
		public void barF(){
			//内部类可以直接访问外部类的数据
			//内部类的对象有一个外部类对象的引用outer,无视访问修饰符
			//outer不是java的关键字
			System.out.println(v1);
		}
	}
}

public class Day121 {
	public static void main(String[] args) {
		//创建了一个外部类的对象
		Foo f = new Foo(10);
		f.fooF();
	}
}

在这里插入图片描述

4.3 局部内部类

例一

//Foo是一个外部类
class Foo {
	private int v1;
	
	public Foo(int v1) {
		super();
		this.v1 = v1;
	}
	
	public void fooF() {
		//Bar是一个局部内部类
		class Bar {
			public void barF(){
				//内部类可以直接访问外部类的数据
				//内部类的对象有一个外部类对象的引用outer,无视访问修饰符
				//outer不是java的关键字
				System.out.println(v1);
			}
		}
		
		Bar bar = new Bar();
		bar.barF();
	}
}

public class Day121 {
	public static void main(String[] args) {
		//创建了一个外部类的对象
		Foo f = new Foo(10);
		f.fooF();
	}
}

在这里插入图片描述

例2.1

//Foo是一个外部类
class Foo {
	private int v1;
	
	public Foo(int v1) {
		super();
		this.v1 = v1;
	}
	
	public void fooF() {
		Bar bar = new Bar();
		bar.barF();
	}
	
	//Bar是一个局部内部类
	class Bar {
		public void barF(){
			//内部类可以直接访问外部类的数据
			//内部类的对象有一个外部类对象的引用outer,无视访问修饰符
			//outer不是java的关键字
			System.out.println(v1);
		}
	}
}

public class Day121 {
	public static void main(String[] args) {
//		//创建了一个外部类的对象
//		Foo f = new Foo(10);
//		f.fooF();
		
		//创建内部类的对象,必须有外部类的对象
		Foo f = new Foo(10);
		Foo.Bar bar = f.new Bar();// f.new Bar(); ->new Bar(f);
		bar.barF();		
	}
}

在这里插入图片描述
例2.2

//Foo是一个外部类
class Foo {
	private int v1;
	
	public Foo(int v1) {
		super();
		this.v1 = v1;
	}
	
	public void fooF() {
		Bar bar = new Bar();
		bar.barF();
	}
	
	//Bar是一个局部内部类
	class Bar {
		public void barF(){
			//内部类可以直接访问外部类的数据
			//内部类的对象有一个外部类对象的引用outer,无视访问修饰符
			//outer不是java的关键字
			System.out.println(v1);
		}
	}
}

public class Day121 {
	public static void main(String[] args) {
//		//创建了一个外部类的对象
//		Foo f = new Foo(10);
//		f.fooF();
		
		//创建内部类的对象,必须有外部类的对象
		Foo f = new Foo(10);
		//使用f.new Bar() 编译器会将f作为参数传递给Bar的构造函数
		Foo.Bar bar1 = f.new Bar();// f.new Bar(); --->  new Bar(f);
		bar1.barF();	
		
		Foo.Bar bar2 = f.new Bar();
		bar2.barF();
	}
}

在这里插入图片描述

局部内部类可以使内部类无法被外部察觉。

4.4 静态内部类

有时候使用内部类只是为了把一个类隐藏在另个一个类的内部,并不需要内部类引用外部类的对象。
这种情况可以使用静态内部类。

4.5 匿名内部类

4.6 练习

将Frock类声明为抽象类,在类中声明抽象方法calcArea方法,用来计算衣服的布料面积。
编写Shirt类继承Frock类,实现calcArea方法,用来计算衬衣所需的布料面积(尺寸 * 1.3)。
编写Coat类继承Frock类,实现calcArea方法,用来计算外套所需的布料面积(尺寸*1.5)。
编写Test类,测试calcArea方法。

/*
 *将Frock类声明为抽象类,在类中声明抽象方法calcArea方法,用来计算衣服的布料面积。
 *编写Shirt类继承Frock类,实现calcArea方法,用来计算衬衣所需的布料面积(尺寸 * 1.3)。 
 *编写Coat类继承Frock类,实现calcArea方法,用来计算外套所需的布料面积(尺寸*1.5)。
 *编写Test类,测试calcArea方法。
 */
package day11;

abstract class Frock {
	protected int size;
	protected abstract double calcArea();
	
}

class Shirt extends Frock {
	public Shirt(int size) {
		this.size = size;
		
	}
	@Override
	protected double calcArea() {
		return size * 1.3;
	}
	
}

class Coat extends Frock {
	public Coat (int size) {
		this.size = size;
	}
	@Override
	protected double calcArea() {
		return size * 1.5;
	}	
}


public class Day122 {
	public static void main(String[] args) {
		Shirt s = new Shirt(170);
		System.out.println(s.calcArea());
		
		Coat c = new Coat(180);
		System.out.println(c.calcArea());
	}
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值