类的继承
继承的特点 --- 破坏了封装
(1)提高了代码的复用性
(2)让类与类之间产生了关系,有了这个关系,才有了多态的共性
1.Java继承具有单继承的特点,不支持多继承
因为多继承容易带来安全隐患,当多个父类中定义了相同的功能(同名函数),当功能内容不同时,子类对象不确定运行哪一个
但是Java保留了多继承的这种机制,只是用另一种表现形式来完成表示-----多实现的方式
Java支持多层继承,也就是一个继承体系
当继承体系较为麻烦的时候,把握这么一个原则:查阅父类功能,创建子类使用功能
2.Java中的继承通过extends关键字来实现,语法格式如下:
修饰符 class SubClass extends SuperClass
{
//类定义部分
}
4.如果定义一个Java类时并未显式指定这个类的直接父类,则这个类默认扩展java.lang.Object类。因此java.lang.Object类是所有类的父类,要么是其直接父类,要么是其间接父类,因此Java对象都可以调用java.lang.Object类所定义的实例方法。
5.重写父类的方法(子父类中函数的特点)
(1)子类包含与父类同名方法的现象称为方法重写,也称为方法覆盖,可以说子类重写了父类的方法或者子类覆盖了父类的方法。子父类方法必须一模一样,连返回值都必须得一样。
(3)当子类覆盖了父类的方法后,子类的对象将无法访问父类中被覆盖的方法,但可以在子类方法中调用父类中被覆盖的方法,如果要在子类方法中调用父类中被覆盖的方法,则可以使用super(被覆盖的是实例方法)或者父类类名(被覆盖的是类方法)作为调用者来调用父类中被覆盖的方法。
(3)注意事项
1. 子类方法覆盖父类方法,必须保证子类方法的访问权限大于或等于父类方法,否则编译失败
2.覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法
6.super限定
super:代表父类对象的引用
super的用法和this的用法几乎一致,在静态方法中不允许使用super和this关键字
在子类定义的实例方法中可以通过super来访问父类中被隐藏的实例变量。
例:
class BaseClass //父类
{
public int a = 5;
}
public class SubClass extends BaseClass
{
public int a = 7;
public void accessBase()
{
System.out.println(a);
}
public void accessSub()
{
//访问从父类继承得到的a实例变量
System.out.println(super.a);
}
public static void main(String[] args)
{
SubClass sc = new SubClass();
sc.accessBase();
sc.accessSub();
}
}
7.子父类中变量的特点
如果在子类中定义了与父类已有变量同名的变量,那么子类中定义的变量会隐藏父类中定义的变量。注意不是完全覆盖,因此系统在创建子对象时,依然会为父类中定义的、被隐藏的变量分配内存空间。(该情况少见)
如果子类中出现非私有的同名成员变量时
子类要访问本类中的变量用this
子类要访问父类中的同名变量用super
8.子父类中的构造函数
子类不会获得父类的构造器,但是子类构造器里可以通过super调用父类构造器的初始化代码,类似于前面所介绍的一个构造器调用另一个重载的构造器。
class Base //父类
{
protected int size;
protected String name;
Base(int size,String name) //基类构造函数
{
this.size = size;
this.name = name;
}
}
public class Sub extends Base
{
private String color;
//子类构造函数
Sub(int size,String name,String color)
{
//即使父类中的成员变量是私有的,也是可以的
//因为这是在子类构造器中调用父类构造器
super(size,name);
this.color = color;
}
}
子类构造器执行体中即使没有super调用,系统也会在执行子类构造器之前,隐式调用父类无参构造器。因为子类构造函数默认第一行有一条隐式语句super();语句。super();语句会访问父类中的空参数的构造函数。因此父类构造器总会在子类构造器之前执行,不仅如此,执行父类构造器时,系统会再次上溯到其父类构造器...,以此类推,创建任何Java对象,最先执行的总是java.lang.Object类的构造器
如果要访问父类中指定的构造函数,可以通过手动定义super();语句的方式来确定。
super();语句必须在构造函数的第一行。
构造子类对象的时候也会生成父类对象。
************************************************************************ final关键字
final:最终,作为一个关键字,其用法包括以下几种
1.可以修饰类、函数、变量
2.被final修饰的类不可以被继承(为了保护封装),避免被子类复写功能
3.被final修饰的方法不可以被子类复写
4.被final修饰的变量是一个常量,只能被赋值一次,既可以修饰成员变量,又可以修饰局部变量。在描述事物的时候,一些事物的出现值是固定的,那么这是为了增强阅读性,都给这些值起个名字,方便于阅读,而这个值不需要改变,所以加上final修饰符。作为常量,常量的书写规范是所有的字母大写,如果由多个单词组成,单词间通过下划线连接,一般在final修饰的变量前面加上static修饰。
5.内部类定义在类的局部位置上时,只能访问该局部被final修饰的局部变量
************************************************************************
抽象类
1.当多个类中出现了相同的功能,但功能的主体不同,这是可以进行向上抽取的,这时只抽取功能定义,而不抽取功能主体,抽象方法必须存在于抽象类中,功能主体部分由子类复写来实现。
2.抽象类的特点
(1)抽象方法一定在抽象类中
(2)抽象方法和抽象类都必须用abstract修饰,抽象方法中没有方法体
(3)抽象类不可以用new创建对象,不可以实例化
(4)抽象类中的方法要被使用,必须由子类复写所有的抽象方法,建立子类对象调用。如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
注意:抽象类和一般类没有太大的区别,该如何描述事物就如何描述事物
abstract可以修饰类和方法,不可以修饰变量
抽象类中可以不定义抽象方法,这样仅仅是为了不让该类建立对象。
注意理解:功能不确定用抽象
************************************************************************ 接口
1.接口:初期理解,可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来实现。class用于定义类,而interface用于定义接口。
2.接口定义时格式特点
(1)接口中常见定义:常量、抽象方法
(2)接口中的成员都有固定修饰符
常量:public static final
方法:public abstract
即使接口中定义的变量、方法中没有写明上述修饰符,系统也会自动添加,但是为了规范和阅读性,以后在写程序的时候要将固定修饰符写上。
3.接口特点
(1)接口不能创建对象,因为有抽象方法,需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以实例化,否则子类就是一个抽象类。
(2)类和类之间的关系是继承,类和接口之间的关系是实现(用关键字implememts),接口和接口之间的关系也是继承
(3)接口可以被类多实现(即一个类可以同时实现多个接口),其实这是Java对C++多继承的转换方式,以多实现的方式实现C++中的多继承
(4)接口和接口之间是继承关系,用关键字extends,接口和接口之间可以实现多继承
(5)一个类可以在继承一个类的同时实现多个接口
class Test extends classDemo inplements InterA,InterB
{ }
注意:基本功能定义在类中,扩展功能定义在接口中
找到了组织------继承
干了点副业------实现接口