Java:抽象类和接口

抽象类

抽象类简单来说就是一个类中对于某个方法只进行的声明,没有实现逻辑。如下就是抽象类的语法:

public abstract class Person {

    public abstract void say();

}

很容易就能发现和一般的类编写上面的区别,首先是class前面多了一个abstract关键字,表示Person是一个抽象类,其次就是在声明方法的时候我们也使用了abstract关键字并且对于say方法我们只是进行了声明,而没有代码逻辑。


说完了语法结构,来简单的说一下抽象类的好处。上面我们定义了一个Person(人)类,该类有一个say说话的方法。人类下面有很多细分,例如医生、学生等等,他们的日常话术各不相同,那么在继承的时候就可以对say方法进行实现(实现抽象类,编写抽象类的具体逻辑),这样就满足了他们各自的需要。

public abstract class Student extends Person {

}

注意看我上面的代码,编写了一个学生类,不是说要实现say方法吗。怎么class前面也有一个abstract关键字,这是因为此时我们还没有实现,say这个方法如果你不加abstract会报错,'Student'必须被声明为抽象类,或者在'Person'中实现抽象方法'say()'。OK,下面来实现一下这个抽象方法。

public class Student extends Person {
    @Override
    public void say() {
        System.out.println("我是一个学生!");
    }
}

再来编写一个医生类

public class Doctor extends Person {
    @Override
    public void say() {
        System.out.println("我是一个医生!");
    }
}

好了,两个类编写好了,调用一下看看效果。

public class Main {

    public static void main(String[] args) {
        Student a = new Student();
        a.say();
        Doctor b = new Doctor();
        b.say();
    }
}
我是一个学生!
我是一个医生!

这时候你可能会问抽象类所有的方法都必须是抽象的吗,当然不是。全部都是抽象方法的那是接口,下面就会说。既然不是必须都是抽象方法,那我们就来声明一个方法来看下效果。

public abstract class Person {

    public abstract void say();

    public void info(){
        System.out.println("我们都是人类!");
    }
}

这里给Person增加了一个新的方法。

public class Main {

    public static void main(String[] args) {
        Student a = new Student();
        a.say();
        Doctor b = new Doctor();
        b.say();
        b.info();
    }
}
我是一个学生!
我是一个医生!
我们都是人类!

好了到这里抽象类就说完了,语法什么的很简单,理解概念或者说理解这种编程思想才是重点。最后在使用抽象类的时候有一些问题需要明确一下

  • 不能被实例化,就是不能使用new创建对象。因为抽象类有未被实现的方法(抽象方法)。

  • 如果一个子类继承抽象类,那么必须实现所有抽象方法。如果有未实现的抽象方法,那么子类也必须定义为abstract类。上面的例子中已经提到过了。

  • 抽象类不能使用final声明。final修饰符标识最终的,被final修饰的类是没有子类的,而抽象类必须有子类才有意义。

  • 抽象类是有构造方法的。虽然我们自己不能new对象去执行构造方法,但是在子类对象实例化的时候,已经对父类的抽象方法进行了实现,所以jvm会创建父类对象的,也会调用父类中的构造方法的(无参构造方法)。在我们new(创建)子类对象的时候,是会先创建父类对象的,所以执行构造方法的时候也会优先执行父类的构造方法。


接口

下面来看一下接口是什么东东,前面说抽象类的时候也稍微提了一下接口,可能你这时候心里面已经有一个概念了,相信自己你没有错,就是这样。

如果一个类中的全部方法都是抽象方法,全部属性都是全局常量,那么此时就可以将这个类定义成一个接口。

代码实现和语法很简单,所以重点说一下接口的意义和好处。

在我们日常工作中做项目的时候,一个项目是有很多功能的,有些功能是会重复使用的,例如数据存储的功能。这个时候如果有些使用到这个功能的地方需要修改数据存储功能的逻辑该怎么办,牵一发而动全身。如果我们把这个功能给抽象的话,在使用的时候再具体实现就可以解决这个问题了。当然你会说每一次使用都要重新实现也太麻烦了,可这就是为了降低程序耦合性(可以理解为程序各个功能之间的依赖关系)方便程序扩展的代价。

在工作中你编写的程序会面临各种挑战,没有一个程序是没有bug的,现在没有一直运行下去总会出现bug的(各种影响你程序正常运行的外在因素)。如果你写一个可扩展性极差的程序,修修补补到最后无从下手很难维护。所以写程序就像盖房子,如果想要稳固想要能够面临各种挑战,初始阶段就要做好主够的准备,这个准备决定了这个房子能达到的高度。所以在编写程序的时候,更建议所有的功能都是用抽象的方法,这就用到了接口。其实对于超级大的项目来说,想要提高程序的可扩展性,降低耦合还需要做很多工作,不仅仅是一个接口。

好了啰嗦完了来看一下具体实现吧。

public interface Person {
    public static final String info = "啦啦啦";
    public void say();
}

很简单吧。这里有个问题要提一下因为接口本身都是由全局常量和抽象方法组的,而抽象方法一定是public的修饰符,要不然没办法继承呀(权限低的话其他类无法访问)。


所以say前面的权限修饰符public,和全局常量的声明关键字是可以去掉的。变成这样:

public interface Person {
    String info = "啦啦啦";
    void say();
}

然后来使用一下接口看看效果吧!

public class Student implements Person {
    @Override
    public void say() {
        System.out.println("我是一个学生!");
    }
}
public class Doctor implements Person {
    @Override
    public void say() {
        System.out.println("我是一个医生!");
    }
}

调用看看结果

public class Main {
    public static void main(String[] args) {
        Student a = new Student();
        a.say();
        Doctor b = new Doctor();
        b.say();
        System.out.println(b.info);;
    }
}
我是一个学生!
我是一个医生!
啦啦啦

end…

接口也说完了,最后补充一些接口其他的使用方法,了解了解。


接口的实现 implements

接口可以多实现: 
格式:
class 子类 implements 父接口1,父接口2...{ 

}

以上的代码称为接口的实现。那么如果一个类即要实现接口,又要继承抽象类的话,则按照以下的格式编写即可: 
class 子类 extends 父类 implements 父接口1,父接口2...{ 

}

接口的继承

接口因为都是抽象部分, 不存在具体的实现, 所以允许多继承,例如: 
interface C extends A,B{ }

总结

接口和抽象类的区别:

1、抽象类要被子类继承,接口要被类实现。
2、接口只能声明抽象方法,抽象类中可以声明抽象方法,也可以写非抽象方法。 
3、接口里定义的变量只能是公共的静态的常量(全局常量),抽象类中的变量是普通变量。 
4、抽象类使用继承来使用, 无法多继承。 接口使用实现来使用, 可以多实现(注意哦一个是继承一个是实现) 
5、抽象类中可以包含static方法 ,但是接口中不允许(静态方法不能被子类重写,因此接口中不能声明静态方法) 
6、接口不能有构造方法,但是抽象类可以有。(接口的继承不同于类的继承)

你可能感兴趣的:(java)