抽象类
在我们定义一些子类的是发现其中有相同行为,那么可以将这些相同的行为抽取出到父类,这些行为只能由具体的子类去实现,抽象类中只声明该函数,所以父类当中的这个函数就不能具体实现,不能有具体的函数体,所以讲该函数定义为抽象函数,具有抽象函数的类 就称之为抽象类。
抽象类的特点
- 抽象类和抽象方法都需要被abstract修饰。抽象方法一定要定义在抽象类中。
- 抽象类不可以创建对象。
- 如果一个子类继承自抽象类时,如果没有完全重写抽象函数,那么这个类也必须是抽象的。
- 抽象类不一定要有抽象函数。但是该抽象类就没啥意义,仅仅是不让该类创建对象。
- 只有覆盖了抽象类中的所有抽象方法后,其子类才可以实例化。
注意
-
抽象类一定是个父类。因为不断抽取而来。
-
抽象类有构造函数,虽然不能给自己的对象初始化,但是可以给自己的子类对象初始化。
-
抽象类关键字abstract不可以和哪些关键字共存?
-
final:final修饰的类是无法被继承的,而abstract修饰的类一定要有子类。final修饰的方法无法被覆盖。但是abstract修饰的方法必须要被子类去实现的。
-
static:静态修饰的方法属于类的,它存在与静态区中,就和对象就没关系了。而抽象方法没有方法体。使用类名调用它没有任何意义。
-
private:私有的方法子类是无法继承到的,也不存在覆盖。
抽象类和一般类的异同
- 相同
- 都用来描述事物的。
- 都可以定义属性和行为。
- 不同
- 一般类可以具体的描述事物,抽象类描述事物的信息不具体。
- 抽象类中可以多定义一个成员:抽象函数。
- 一般类可以创建对象,而抽象类不能创建对象。
例题
写一个抽象图形类,分别计算圆,矩形的周长和面积。通过继承实现。
public class GraphTest{
public static void main(String[] args){
Circle c=new Circle(2);
System.out.println(c.Area());
System.out.println(c.Long());
}
}
abstract class Graph{
public abstract double Area();
public abstract double Long();
}
class Circle extends Graph{
private double r;
public Circle(double r){
this.r=r;
}
@Override
public double Area(){
return (Math.PI)*r*r;
}
@Override
public double Long(){
return (Math.PI)*r*2;
}
}
class Rectangle extends Graph{
private double height;
private double width;
public Rectangle(double height,double width){
this.height=height;
this.width=width;
}
@Override
public double Area(){
return height*width;
}
@Override
public double Long(){
return 2*(height+width);
}
}
接口
- 如果一个抽象类中所有的方法都是抽象的,那么这个抽象类就可以用接口去表述 ,接口就是一个特殊的抽象类。
接口的特点
- 为类添加功能
- 作为一种中间传递
- 接口之间是多继承,因为只保留函数声明,并未指定具体执行,所以不会产生二义性。
接口中成员的特点
-
接口里面的变量一律是public static final 不能改变的。
-
接口里面的函数一律是 ,public abstract 隐藏的默认的。
-
接口中的成员都是公共的。
-
接口就是一个特殊的抽象类。
-
子类必须覆盖掉接口中的所有抽象方法,子类才可以实例化。否则子类是一个抽象类。
接口和抽象类的区别
- 相同点
都位于继承的顶端,用于被其他实现或继承
都不能实例化
都包含抽象方法,其子类都必须覆写这些抽象方法
- 区别
抽象类为部分方法提供实现,避免子类重复实现这些方法,提供代码重用性;接口只能包含抽象方法
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口
例子
写一个既继承又实现接口的类
class InterfaceDemo02{
public static void main(String[] args){
拉布拉多 卡夫卡=new 拉布拉多();
卡夫卡.叫();
卡夫卡.导盲();
卡夫卡.缉毒();
}
}
interface 导盲功能{
public void 导盲();
}
interface 缉毒功能{
public void 缉毒();
}
interface 拆家功能{
public void 拆家();
}
abstract class 动物{
public abstract void 叫();
}
class 拉布拉多 extends 动物 implements 导盲功能,缉毒功能{
@Override
public void 叫(){
System.out.println("我是拉布拉多");
}
@Override
public void 导盲(){
System.out.println("我会导盲");
}
@Override
public void 缉毒(){
System.out.println("我会缉毒");
}
}
class 黑背 extends 动物{
@Override
public void 叫(){
System.out.println("我是黑背");
}
}
class 二哈 extends 动物{
@Override
public void 叫(){
System.out.println("我是二货");
}
}
多态
多态的前提是继承,同一事物在不同的场合具有不同的形态,在面向对象中如何去表示多态?父类的引用指向一个子类的对象。例如:Fu f=new Zi();其中Zi类继承Fu类。父类对象无法转成子类对象。
多态中成员函数的特点
- 如果子类没有重写 则调用父类的
- 如果子类重写 则调用子类
- 如果父类中没有 子类的特有行为不能调用
多态中成员变量的特点
只能调用父类中的成员变量 子类的特有属性不能调用
内部类
将类写在其他类的内部,可以写在其他的成员位置和其他类的局部位置,这时写在其他类内部的类就成为内部类。
内部类访问规则
内部类可以直接访问外部类中的成员,但外部类不能直接访问内部类,若要访问,必须创建内部类对象才能访问