面向对象_继承_super关键字_访问权限修饰符等

2019-01-19~20

主要学习了继承、super关键字、访问权限修饰符、方法重写、final关键字、多态、抽象类、接口

继承

为什么需要继承?
例如:小学生、中学生、大学生,他们都有姓名、年龄、学号的属性,交学费的行为
把他们相同的属性和行为抽取出来放到单独的一个学 d生类中,小学生、中学生、大学生只需要继承就好了,大大的减少了代码
总结:类似对对象的抽取,继承是对某一批类的抽象
继承的理解

  1. 继承是对一批类的抽象
  2. 继承本质就是向上抽取代码,也就是说如果多个类出现重复代码,我们可以定义一个类来存储这些重复代码,并且给这个类取一个名字就好了

继承的格式:
通过extends关键字就可以实现类与类的继承
class 子类名 extends 父类名 { }
被继承的这个类叫父类,基类或者超类
继承的这个类称为子类或者派生类
继承的好处:
3. 简化了代码
4. 提高了代码的维护性和可扩展性
5. 让类与类之间产生关系,这是多态的必要条件
继承的缺点:
开发设计的原则:高内聚,低耦合
类与类之间的关系不要太高,尽量保证类与类之间的独立性
1.造成耦合性过高
2.牵一发动全身 A B C D extends X(go())
继承要慎用

继承的特点

  1. 单一继承性(一个儿子只有一个爸爸)
  2. java支持多层继承,不支持多继承
    class Son extends Father{}
    class Father extends GrandFather{}
  3. 如果一个父类的成员变量使用private关键字修饰,那么对子类成员不可见
    一般父类成员使用protected和public修饰
  4. 如果一个子类不仅可以继承父类的所有公共方法和属性,还可以有自己的方法
  5. 子类不能继承父类的构造方法

什么时候用继承?

  1. 存在公共代码
  2. 满足A is a B

如何继承?

  1. 先写子类
  2. 观察多个子类之间是否存在公共代码
  3. 存在就将公共代码抽取出来,放置在父类中
  4. 将子类继承父类
  5. 将子类的公共代码删除
super关键字

this和super用法类似,this代表本类引用,super代码父类引用
this和super的对比使用
访问成员变量
this.成员变量 super.成员变量
访问构造方法
this():访问本类无参构造 this(参数列表) 访问本类带参构造
super():访问本类无参构造 super(参数列表) 访问本类带参构造
访问成员方法
this.成员方法():访问本类成员方法
super.成员方法():访问父类成员方法
this和super的区别
this表示访问当前对象,super表示访问父类对象
既然super理解为一个父类对象,那么super应该可以用父类的成员

this主要作用是用来帮我们初始化本类成员(当外界传入的变量名和本类变量名相同的时候)

任何一个本类成员默认都隐含一个this
任何一个本类成员同时也可以使用super访问父类成员
super特点

  1. 任何一个构造方法都默认会在构造方法的第一句写上super(),访问父类的无参构造方法 Constructor call must be the first statement in a constructor
  2. super和this访问构造方法必须出现在构造方法的第一句
    this和super在访问构造方法的时候,二者不能共享
  3. static静态上下文中不能出现this和super
  4. super的主要作用是帮助我们初始化父类继承过来的成员
访问权限修饰符

为什么需要访问权限修饰符
控制成员(成员变量 成员方法 构造方法)的访问权限
访问权限修饰符
访问权限修饰符的总结

  1. 访问权限修饰符有四个
  2. 访问权限修饰符可以修饰成员变量、成员方法、还可以修饰类(只有public可以)
    在这里需要注意,其实protected/private可以修饰类,但必须是内部类
    四个修饰符特点
  3. public修饰的成员对一切类可见
  4. protected修饰的成员对子类可见
  5. default修饰的成员仅 对同包下可见
  6. private修饰的成员仅对本类可见

访问权限修饰符的宽严关系
public > protected > default > private

Java当中封装就是通过访问权限修饰符来实现的
封装: 就是屏蔽内部的成员,而屏蔽内部的成员是通过访问权限修饰符来控制的

方法重写

为什么需要方法重写?
父类的功能不能满足子类的需求,需要方法重写

方法重写的概念:覆盖父类的方法,实现自己所特有的功能

方法重写的特点:

  1. 发生在具有子父关系 的两个类中
  2. 方法名相同
  3. 参数列表完全相同(参数的个数,顺序,类型都一样)
  4. 返回值类型可以相同或者是其子类
  5. 访问权限修饰符不能严于子类
  6. 子类声明的异常不能够被扩大

访问权限修饰符的宽严关系
public > protected > default > private

方法重写的注意事项

  1. 私有修饰的方法不能够被重写【因为私有的修饰方法不能被继承】
  2. 构造方法不能够被重写
  3. 子类重写父类方法时,访问权限修饰符不能够严于父类
  4. 子类声明的异常不能够被扩大
  5. 重载和重写的区别–>
    重载的特点:发生在一个类中,方法名相同,参数列表不同
    重写的特点:如上所示
  6. 重写是多态的必要条件
final关键字

为什么需要final关键字
final关键字最终的意思
final关键字的特点:

  1. final修饰的类不能够被子类继承
  2. final修饰的方法不能够被子类重写
  3. final修饰变量:不能够被二次赋值,final修饰的变量直接升级为常量
    成员变量:可以声明之后初始化
    局部变量:一定在声明的同时初始化
    常量:
    字面值常量 20 20.5 “ABC”
    自定义常量 public static final int NUM = 10;
多态

为什么需要多态
一个动作在不同环境下变现出来的不同状态
eg: cut
理发师:剪头发
医生:动刀子
导演;暂停

多态的概述:
生活中: 同一个动作在不同的环境下体现出来的不同的状态
代码中: 同一个方法在不同的类下体现出来的不同的实现
内存中: 父类引用指向子类对象
多态在代码中如何来实现的?

  1. 必须要存在继承关系
  2. 必须存在方法重写
  3. 父类引用指向子类对象

多态访问成员的特点:
成员变量:编译时看左边类型,运行时看左边类型
成员方法:编译时看左边类型,运行时看右边类型
构造方法:帮助子类初始化父类继承过来的成员
静态方法:编译时看左边类型,运行时看左边类型

多态的优点:

  1. 简化了代码
  2. 提高了维护性和可扩展性
eg:饲养员给不同的动物喂不同的食物
public class DuoTaiDemo03 {
	public static void main(String[] args) {
		Feeder f = new Feeder();
//		f.feedMeatToTiger(new Tiger(), new Meat());
//		
//		f.feedBambooToPanda(new Panda(), new Bamboo());
		
		Animal an = new Tiger();
		Food food = new Meat();
		f.feed(an, food);
		
		f.feed(new Monkey(), new Banana());
	}
}

//开闭原则: 对扩展开放,对修改关闭
class Feeder{
	// 给老虎喂肉
	/*
	 * 返回值类型: void
	 * 参数列表: Tiger t, Meat m
	 * 方法名: feedMeatToTiger
	 */
	/*public void feedMeatToTiger(Tiger t, Meat m) {
		t.show();
		m.show();
	}
	
	public void feedBambooToPanda(Panda p, Bamboo b) {
		p.show();
		b.show();
	}*/
	
	// 利用多态
	public void feed(Animal an, Food f) {
		// Animal an = new Tiger();
		// Food f = new Meat();
		an.show();
		f.show();
	}
}

class Animal{
	public void show() {
		System.out.println("我是动物");
	}
	
}

class Bear extends Animal{
	@Override
	public void show() {
		System.out.println("我是狗熊");
	}
}

class Tiger extends Animal{
	@Override
	public void show() {
		System.out.println("我是老虎");
	}
}

class Panda extends Animal{
	@Override
	public void show() {
		System.out.println("我是熊猫");
	}
}

class Monkey extends Animal {
	@Override
	public void show() {
		System.out.println("我是猴子");
	}
}


class Food{
	public void show() {
		System.out.println("我是食物");
	}
}

class Meat extends Food{
	public void show() {
		System.out.println("我是肉");
	}
}

class Bee extends Food{
	@Override
	public void show() {
		System.out.println("我是蜂蜜");
	}
}

class Bamboo extends Food{
	public void show() {
		System.out.println("我是竹子");
	}
}

class Banana extends Food {
	@Override
	public void show() {
		System.out.println("我是香蕉");
	}
}

多态的缺点:使用多态不能够访问子类特有的方法
解决办法:向下转型
向上转型(自动转换)
格式:<父类型> <引用变量名> = new <子类型>();
特点:
子类转为父类 父类的引用指向子类对象。自动进行类型转换
此时通过父类引用变量调用的方法是子类覆盖或继承父类的方法
此时通过父类引用变量无法调用子类特有的属性和方法
向下转型(强制类型转换)
格式:<子类型> <引用变量名> = (<子类型> )<父类型的引用变量>;
特点:
父类转为子类,父类引用转为子类对象。强制类型转换
在向下转型的过程中,如果没有转换为真实子类类型,会出现类型转换异常

java.lang.ClassCastException: com.sxt.duotaidemo.Benz cannot be cast to com.sxt.duotaidemo.BMW
ClassCastException: 类型转换异常
产生原因: 在向下转型的过程当中,没有转换成真实的类型
解决办法: 在向下转型的过程当中,对父类类型的所有子类做逐一判断
instanceof关键字
左边对象 instanceof 右边类 这是一个表达式,结果boolean类型
判断左边对象是否属于右边类的实例

抽象类
eg:一个形状类  有三角形 圆形  矩形三个子类
public class AbstractDemo01 {
	public static void main(String[] args) {
		Shape s = new Triangle(2,4);
		System.out.println(s.getArea());
		s = new Circle(2);
		System.out.println(s.getArea());
	}
}

abstract class Shape {
	public abstract double getArea();
}

class Triangle extends Shape {

	private double d;
	private double h;

	public Triangle(double d, double h) {
		super();
		this.d = d;
		this.h = h;
	}

	public Triangle() {
		super();
	}

	@Override
	public double getArea() {
		return d * h / 2;
	}
}

class Circle extends Shape {
	private double r;

	public Circle(double r) {
		super();
		this.r = r;
	}

	public Circle() {
		super();
	}

	@Override
	public double getArea() {
		return 3.14 * Math.pow(r, 2);
	}
}

通过观察发现,父类的getArea方法如果删除,那么多态编译报错,所以父类方法存在有意义
但是父类方法getArea的实现没有意义,像这种用来给子类重写,但是本身有没有任何实现的方法可以定义为抽象方法

格式:访问权限修饰符 abstract 返回值类型 方法名();
Abstract methods do not specify a body
The abstract method getArea in type Shape can only be defined by an abstract class
只要有一个抽象方法的类就必须定义为抽象类
抽象类特点:

  1. 抽象类和抽象方法使用abstract修饰
  2. 有一个抽象方法必须声明抽象类
  3. 抽象类中可以没有抽象方法
  4. 抽象方法的抽象类有意义吗?有意义,不能够实例化,防止外界创建对象
  5. 如果我们想要“实例化”–利用多态
  6. 抽象类的子类特点:
    a.如果子类想要继承抽象类,那么就必须实现抽象类中的抽象方法
    b.如果子类不想要实现抽象类中的抽象方法,可以,子类也升级为抽象类
  7. 抽象类普通类的区别:
    抽象类中 可以有成员变量吗,可以有成员方法吗,静态方法,构造方法吗? 如果有的话有意义吗?
    成员变量 --> 可以给子类使用
    成员方法 --> 可以给子类使用
    构造方法 --> 帮助子类初始化父类继承过来的成员
    抽象方法 --> 可以给子类重写
    燃烧自己,照亮孩子
    ==所以抽象本质就是一个服务类,服务于所有的子类 ==
  8. private final static 可以用来修饰抽象方法吗
    private修饰的方法不能够被子类继承,abstract修饰的方法希望被子类重写,二者冲突
    final修饰的方法不能够被子类重写,abstract修饰的方法希望被子类重写,二者冲突
    static修饰方法用来方便调用,某个方法的调用肯定是需要功能的实现,而abstract修饰的方法没有方法体,调用就毫无意义,二者没有意义
  9. 即热抽象类是一个服务类,服务于子类所以抽象类一般都是用public protected
接口

生活中的接口是指某些企业和组织等制定的
一种约定或标准(USB)

USB风扇按照电脑产商的USB接口设计生产
就可以使得电脑具备风扇散热的功能。
USB鼠标按照电脑产商的USB接口设计生产
就可以使得电脑具备鼠标移动的功能。
U盘按照电脑产商的USB接口设计生产
就可以使得电脑具备U盘存储的功能。

生活中的接口的理解
1.接口是一种规范,是一种标准
2.接口还能够扩展功能
3.接口是即插即拔,是灵活的
接口概念:接口就是抽象方法和常量的集合,接口是比抽象类更抽象的类

接口的特点:

  1. 接口使用interface修饰
  2. 接口就是抽象方法和常量的集合,接口是比抽象类更抽象的类,在JDK8以后,接口可以有静态方法和默认方法
  3. 接口成员变量默认都是常量默认会省略public static final,接口中的成员都是抽象方法,默认使用 public abstract修饰
  4. 接口不能实例化,如果需要实例化,可以利用多态
  5. 接口子类的特点:
    a.如果一个实现某接口,那么就必须实现接口里面的抽象方法
    b.如果子类不想要实现接口,那么子类也可以升级为接口
  6. 接口是一种规范
  7. 接口是灵活的
  8. 接口是用来扩展功能的,还是继承者本身的实现
  9. 接口和类的关系
    类和类 单继承 不可以实现
    类和接口 多实现 不可以继承
    接口和接口 多继承 不可以实现
  10. 接口和继承的区别
    什么时候使用接口,什么时候使用继承?
    大部分情况下都是使用接口,因为接口的灵活,降低了耦合性。而且接口是一种规范
    继承主要体现在代码的抽取,如果出现了重复代码就使用继承
    或者需要使用父类的某个功能
  11. 面向接口的编程
多态的应用

作为形参
基本类型
引用类型
普通类
当一个形参希望我们传入一个普通类时,我们实际上传入的是该类的对象/匿名对象
抽象类
当一个形参希望我们传入一个抽象类时,我们实际上传入的是该类的子类对象/子类匿名对象
接口
当一个形参希望我们传入一个接口时,我们实际上传入的是该类的实现类对象/实现类匿名对象
作为返回值
基本类型
引用类型
普通类
当一个方法的返回值是一个普通类时,实际上返回的是该类的对象,我们可以使用该类的对象接收
抽象类
当一个方法的返回值是一个抽象类时,实际上返回的是该抽象类的子类对象,我们可以使用该抽象类接收
接口
当一个方法的返回值是一个接口时,实际上返回的是该接口的实现类对象,我们可以使用接口接收
当返回值类型是引用类型时,可以使用链式调用

内部类

为什么需要内部类?

  1. 提高类独栋安全性
  2. 防止外界创建对象

什么情况下可以不让外界创建对象

  1. 抽象类
  2. 接口
  3. 内部类
  4. 构造方法私有化

内部类的概念:在类中定义一个类叫内部类
内部类的分类
成员内部类
局部内部类
静态内部类
匿名内部类

内部类的特点:

  1. 外部类可以直接访问内部类成员,包括私有
  2. 内部类通过编译器生成字节码文件的格式:外部类$内部类
  3. 外界需要访问内部类可以通外部创建内部类对象
  4. 外界也可以通过如下格式创建内部类对象
    外部类.内部类 对象名=new 外部类.new内部类;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值