抽象类
- 抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象
- 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,避免子类设计的随意性。
有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法
抽象类不能被实例化,只能当作父类被继承。
抽象类的编程
public abstract class shape {
public abstract double getArea();
/**
* 比较两个形状的大小
* @param p 另一个形状的实例
* @return 如果当前形状较大则返回true
*/
public boolean compareArea(shape p){
return this.getArea()>p.getArea();
}
}
抽象方法作为父类申明了抽象的getArea()方法
public class Circle extends shape {
double redius;
public Circle(double redius){
this.redius =redius;
}
@Override
public double getArea() {
return Math.PI*redius*redius;
}
}
子类实现抽象类,重写父类抽象方法
public class Reactanger extends shape {
double length;
public Reactanger(double length){
this.length=length;
}
@Override
public double getArea() {
return length*length;
}
}
创建子类对象,调用重写方法,比较两者的面积,进行打印
public static void main(String[] args) {
shape cir = new Circle(2.33);
shape rea = new Reactanger(8.0);//此处用父类类型的引用变量和子类类型的引用变量一样,因为都是指向子类对象
System.out.println(cir.getArea());
System.out.println(rea.getArea());
System.out.println(cir.compareArea(rea));
}
接口
接口概念
- 接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。
接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计。
请记住:一切事物均有功能,即一切事物均有接口
接口的定义
- 与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。
定义格式
public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
- 接口中的方法均为公共访问的抽象方法
接口中无法定义普通的成员变量
类实现接口
- 类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。
其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。
格式
class 类 implements 接口 {
重写接口中方法
}
接口成员的特点:
1、接口中可以定义变量,但是变量必须有固定的修饰符修饰,public static final 所以接口中的变量也称之为常量,其值不能改变。
2、接口中可以定义方法,方法也有固定的修饰符,public abstract
3、接口不可以创建对象。
4、子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化。否则子类是一个抽象类。
interface Demo { ///定义一个名称为Demo的接口。
public static final int NUM = 3;// NUM的值不能改变
public abstract void show1();
public abstract void show2();
}
//定义子类去覆盖接口中的方法。类与接口之间的关系是 实现。通过 关键字 implements
class DemoImpl implements Demo { //子类实现Demo接口。
//重写接口中的方法。
public void show1(){}
public void show2(){}
}
接口的多实现
interface Fu1
{
void show1();
}
interface Fu2
{
void show2();
}
class Zi implements Fu1,Fu2// 多实现。同时实现多个接口。
{
public void show1(){}
public void show2(){}
}
- 怎么解决多继承的弊端?
弊端:多继承时,当多个父类中有相同功能时,子类调用会产生不确定性。
其实核心原因就是在于多继承父类中功能有主体,而导致调用运行时,不确定运行哪个主体内容。
为什么多实现能解决?
因为接口中的功能都没有方法体,由子类来明确。
类继承类同时实现接口
1、接口和类之间可以通过实现产生关系,同时也学习了类与类之间可以通过继承产生关系。当一个类已经继承了一个父类,它又需要扩展额外的功能,这时接口就派上用场了。
2、子类通过继承父类扩展功能,通过继承扩展的功能都是子类应该具备的基础功能。如果子类想要继续扩展其他类中的功能呢?这时通过实现接口来完成。
class Fu {
public void show(){}
}
interface Inter {
pulbic abstract void show1();
}
class Zi extends Fu implements Inter {
public void show1() {
}
}
- 学习类的时候,知道类与类之间可以通过继承产生关系,接口和类之间可以通过实现产生关系,那么接口与接口之间会有什么关系。
多个接口之间可以使用extends进行继承。
interface Fu1{
void show();
}
interface Fu2{
void show1();
}
interface Fu3{
void show2();
}
interface Zi extends Fu1,Fu2,Fu3{
void show3();
}
内部类
- 将类写在其他类的内部,可以写在其他类的成员位置和局部位置,这时写在其他类内部的类就称为内部类。其他类也称为外部类
什么时候使用内部类
class 汽车 { //外部类
class 发动机 { //内部类
}
}
内部类可以直接访问外部类的所有成员
成员内部类
- 成员内部类,定义在外部类中的成员位置。与类中的成员变量相似,可通过外部类对象进行访问
成员内部类代码演示
class Body {//外部类,身体
private boolean life= true; //生命状态
public class Heart { //内部类,心脏
public void jump() {
System.out.println("心脏噗通噗通的跳")
System.out.println("生命状态" + life); //访问外部类成员变量
}
}
}
访问内部类
public static void main(String[] args) {
//创建内部类对象
Body.Heart bh = new Body().new Heart();
//调用内部类中的方法
bh.jump();
}
- 不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
1、外部类.this.成员变量
2、外部类.this.成员方法
局部内部类
class 外部类 {
修饰符 返回值类型 方法名(参数) {
class 内部类 {
//其他代码
}
访问内部类
public static void main(String[] args) {
//创建外部类对象
Party p = new Party();
//调用外部类中的puffBall方法
p.puffBall();
}
匿名内部类
代码演示:
//已经存在的父类:
public abstract class Person{
public abstract void eat();
}
//定义并创建该父类的子类对象,并用多态的方式赋值给父类引用变量
Person p = new Person(){
public void eat() {
System.out.println(“我吃了”);
}
};
//调用eat方法
p.eat();
使用匿名对象的方式,将定义子类与创建子类对象两个步骤由一个格式一次完成,。虽然是两个步骤,但是两个步骤是连在一起完成的。
匿名内部类如果不定义变量引用,则也是匿名对象。代码如下:
new Person(){
public void eat() {
System.out.println(“我吃了”);
}
}.eat();
静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。