前言
在我们java开发过程中,抽象类是我们经常会用到的一种类型,那么什么是抽象类,我们在使用的时候有没有什么需要注意的地方呢?
不着急,让我们先看下面一段代码:
class Graph{
public void Show(){
System.out.println("这是一个图形");
}
}
class Triangle extends Graph{
@Override
public void Show(){
System.out.println("▲");
}
}
class Rectangle extends Graph{
@Override
public void Show(){
System.out.println("■");
}
}
class Cycle extends Graph{
@Override
public void Show(){
System.out.println("⚪");
}
}
public class show {
public static void main(String[] args) {
Graph[] graphs = {new Cycle(), new Triangle(), new Rectangle()};
for (Graph graph1: graphs) {
graph1.Show();
}
}
}
上面这段代码我们通过创建父类,然后让各子类继承父类的方法将父类方法重写后分别打印出了我们想要的圆形,三角形,矩形。但我们会发现,上面代码中的父类Graph中的Show函数其实并没有被用到,那么我们是否可以简写为public void Show()呢?答案是肯定的,但是我们接下来要用到抽象类。
抽象类
定义:在类名与方法名前加上abstract修饰符
例如我们上面定义的Graph类,也可以这么写将它变为抽象类:
abstract class Graph{
abstract public void Show();
}
抽象类的使用方法与注意点:
关于抽象类的使用与注意点,博主整理了以下11点:
1.抽象类不能被实例化。 不能new 抽象名();
抽象类,故名思意,就是很抽象的一种东西,我们是不能将其实例化的,若要实例化编译器则会报错。
2.使用abstract修饰的方法,就是抽象方法
我们也可以在抽象类中写入非抽象方法,在抽象类被子类继承后,可以不重写,直接使用非抽象方法:
abstract class Graph{
abstract public void Show();
public void func(){
System.out.println("抽象里面也可以有不抽象的方法");
}
}
3.里面的成员变量和成员方法与普通类都是一样的,只是该抽象类不能实例化。
抽象类与平常类除了无法被实例化与其子类一定要将抽象方法重写这两个不同点外,就没有区别了。其他还是该怎么使用怎么使用。
//父类
abstract class Graph{
public int a = 10;//父类定义一个int类型变量
abstract public void Show();
public void func(){
System.out.println("抽象里面也可以有不抽象的方法");
}
}
//子类
class Triangle extends Graph{
@Override
public void Show(){
System.out.println("▲");
}
public void PrintSubclass(){
System.out.println(super.a);
}
}
public class shishi {
public static void main(String[] args) {
Triangle tri = new Triangle();
tri.PrintSubclass();
}
}
4.当一个普通类继承抽象类之后,必须把抽象类中的所有抽象方法都重写一遍。
5.抽象类的使命就是被继承
6.抽象类也可以向上转型,进一步形成多态
abstract class Graph{
public int a = 10;//父类定义一个int类型变量
abstract public void Show();
public void func(){
System.out.println("抽象里面也可以有不抽象的方法");
}
}
class Triangle extends Graph{
@Override
public void Show(){
System.out.println("▲");
}
public void shishi(){
System.out.println(super.a);
}
}
class Rectangle extends Graph{
@Override
public void Show(){
System.out.println("■");
}
}
class Cycle extends Graph{
@Override
public void Show(){
System.out.println("⚪");
}
}
public class shishi {
//向上转型实现多态
public static void draw(Graph graph){
graph.Show();
}
public static void main(String[] args) {
draw(new Rectangle());
draw(new Triangle());
draw(new Cycle());
}
}
7.当一个抽象类A继承了抽象类B,那么A可以补充些抽象B中的方法
8.当一个普通的类C继承了第7条的A,此时就得重写所有的抽象方法
A可以补充抽象类的方法,但当一个普通类C继承B的时候,哼哼~出来混是要还滴。C要把A和B中的抽象方法全部重写一次。
abstract class A{
abstract void func1();
}
abstract class B extends A{
abstract void func2();
}
class Test extends B{
public void func1(){
System.out.println("这个是A的抽象方法重写");
}
public void func2(){
System.out.println("这个是B的抽象方法重写");
}
}
public class boke {
public static void main(String[] args) {
Test test = new Test();
test.func1();
test.func2();
}
}
输出结果:
9.final不能修饰抽象方法和抽象类
我们都知道final修饰符定义在前面就代表说该变量或方法无法再被赋值或者是重写,但抽象类是一定要被重写的,若再抽象类前加上final,就相当于自相矛盾了。
10.抽象方法也不能是private
private代表只能在该代码块内使用,但抽象方法一定要在子类中被重写,所以在抽象方法前加上private就与抽象方法要被重写的性质冲突了,会报错。
11.抽象类当中不一定有抽象方法,但是这个抽象方法上,一定会有抽象类
接口
接口的出现其实是为了弥补java中单继承机制。
接口:一种行为的标准和规范
接口可以看成是:多个类的公共规范,是一种引用数据类型
如果觉得以上的定义看起来有些虚的话,我们可以先看下面接口的使用方法以及注意点来了解接口。
接口的使用方法以及注意点
1.接口使用关键字interface来修饰,大驼峰来命名。
2.接口当中的成员方法,只能是抽象方法。所有的方法默认为public abstract
3.接口当中的成员变量,默认是public static final。
4.接口当中的方法,如果要实现,必须在前面加上default
interface IShape{
//成员变量
public static final int a = 10;
//成员方法
void func();
//如果非要实现
default void func2(){
System.out.println("这是在接口中对具体方法的实现");
}
}
5.接口当中的静态方法,也可以有具体的实现。
interface IShape{
//成员变量
public static final int a = 10;
//成员方法
void func();
//如果非要实现
public static void Try2(){
System.out.println("这个也可以实现具体方法");
}
}
6.接口不能进行实例化。不能new接口
7.一个普通的类可以通过implement来实现接口
8.一个类,可以继承抽象类,同时实现多个接口。每个接口之间使用逗号来分割。
9.类和接口用implement,接口和接口用extends
Tips:一个源文件中只能有一个主类或者主接口,所以非所有class和interface能同时加上访问修饰符。
为了让我们更深刻地理解接口是一种行为的规范与代替。可以看下面的代码:
class Animal{
public String name;
public int age;
public Animal(String name,int age){
this.name = name;
this.age = age;
}
public void eat(){
System.out.println(this.name + "吃饭");
}
public void sleep(){
System.out.println(this.name + "睡觉");
}
}
interface IRun{
void Run();
}
class Dog extends Animal implements IRun{
public Dog(String name,int age){
super(name,age);
}
@Override
public void eat(){
System.out.println(this.name + "吃狗粮");
}
@Override
public void Run(){
System.out.println(this.name + "is dog 会跑步");
}
class Robot implements IRun{
@Override
public void Run(){
System.out.println("机器人也有跑步这一行为");
}
}
public class practice1 {
public static void Run(IRun irun){
irun.Run();
}
public static void main(String[] args) {
Dog dog = new Dog("修勾",2);
Robot robot = new Robot();
dog.Run();
robot.Run();
Run(robot);
Run(dog);
}
}
就如上面,虽然机器人与修勾没有相同父类,也不是同种生物,但他们都有“能够跑步”这一行为。
以上便是抽象类和接口的全部啦!又是收获满满的一天~