一、抽象类

// 抽象类Shape
public abstract class Shape
{
// 1. 成员变量
private String color; // 2. 初始化块
{
System.out.println("执行Shape的初始化块...");
} // 3. 构造器
public Shape() {}
public Shape(String color)
{
System.out.println("执行Shape的构造器...");
this.color = color;
} // 4. 方法:抽象方法和普通方法都可以
public abstract double calPerimeter();
public void setter(String color)
{
this.color = color;
} // 5. 内部类(接口、枚举)
}

1. 抽象方法

  • 抽象方法没有方法体(只有方法签名,没有方法实现),只能由子类提供实现(即重写)
  • 抽象方法必须能被其子类重写才有意义,即private和abstract不能同时修饰某个方法
  • final修饰的方法不能被重写,因此final和abstract不能同时修饰某个方法
  • 类方法不能被定义成抽象方法,即static和abstract不能同时修饰某个方法
  • 含有抽象方法的类只能被定义成抽象类

2. 抽象类

  • 抽象类不能被实例化(不能创建抽象类的实例),只能当作父类被其他子类继承
  • final修饰的类不能被继承,因此final和abstract永远不能同时使用
  • 子类只有实现抽象父类里的所有抽象方法,才能被定义成普通类

3. 抽象类的成员:成员变量、方法、初始化块、构造器、内部类(接口、枚举)

  • 抽象类里可以没有抽象方法
  • 抽象类中的初始化块和构造器都不是在创建该类对象时被调用的(抽象类的构造器不能用于创建实例),而是在创建其子类的实例时被调用

4. 利用抽象类可以发挥多态的优势,使程序更加灵活

// 下面定义一个Circle普通类,其必须实现Shape里的抽象方法
public class Circle extends Shape
{
private double radius;
public Circle(String color, double radius)
{
super(color);
this.radius = radius;
} public void setRadius(double radius)
{
this.radius = radius;
} // 重写Shape类的计算周长的抽象方法
public double calPerimeter()
{
return 2 * Math.PI * radius;
} public static void main(String[] args)
{
// 定义Shape类型的引用变量s,s指向Circle对象
Shape s = new Circle("黄色", 3); // 由于在Shape类中定义了calPerimeter()方法,所以程序可以直接调用变量s的calPerimeter()方法
// 无须将变量s强制转换为其子类类型
System.out.println(s.calPerimeter());
}
}

5. 抽象类的作用

  不同Shape子类对周长的计算方法是不一样的,即Shape类无法准确地知道其子类计算周长的方法,故Shpe类不知道如何实现calPerimeter()方法。此时若不在Shape类中定义calPerimeter()方法,则Shape引用变量s虽然可以引用到Shape子类的实例,但该变量s却无法调用calPerimeter()方法,必须将其强制转换为其子类类型才行,这就降低了程序的灵活性。这种情况下,我们可以在Shape类中将calPerimeter()方法定义为抽象方法,其具体实现交给子类来完成。也就是说,抽象父类把不能实现的方法定义为抽象方法,留给其子类去实现。

  • 从语义的角度来看,抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象
  • 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类设计的随意性
  • 抽象类体现的是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会大致保留抽象类的行为方式

二、接口

/*
* 示例:定义一个接口
*/
[修饰符] interface 接口名 extends 父接口1, 父接口2...
{
// 成员1:静态常量
[public static final int] MAX_SIZE = 50; // 成员2:抽象方法
[public abstract] void getData(String msg); // 成员3:默认方法
[public] default void test()
{
System.out.println("默认的test()方法");
} // 成员4:类方法
[public] String staticTest()
{
return "接口里的类方法";
} // 成员5:私有方法
private void foo()
{
System.out.println("foo私有方法");
}
private static void bar()
{
System.out.println("bar私有静态方法");
} // 成员6:内部类、内部接口、内部枚举
}

1. 定义接口概述

  • 定义接口使用interface关键字
  • 修饰符可以是public或省略,如果省略了public访问控制符,则默认采用包权限访问控制符
  • 接口名应与类名采用相同的命名规则,通常使用形容词
  • 接口只能继承接口,且接口支持多继承(可以有多个直接父接口)
  • 一个Java源文件里最多只能有一个public接口,且如果某Java源文件里定义了一个public接口,则该文件名必须与public接口名相同

2. 接口的成员

由于接口里定义的是多个类共同的公共行为规范,因此接口里的成员(除了私有方法)都是public访问权限。

定义接口成员(除了私有方法)时,既可以显式使用public修饰符,也可以省略不写(此时系统会自动添加public修饰符)。

①静态常量

  • 接口里的成员变量只能是静态常量,它们是接口相关的
  • 在接口中定义成员变量时,不管是否使用public static final修饰符,接口里的成员变量总是使用这三个修饰符来修饰(系统自动添加)
  • 由于接口里没有初始化块和构造器,因此接口里的静态常量只能在定义时指定默认值

②抽象方法(无方法体)

  • 由于接口里定义的方法只能是抽象方法、类方法、默认方法和私有方法,因此如果不是定义后三种方法,系统将自动为普通方法增加abstract修饰符
  • 定义接口里的普通方法时,不管是否使用public abstract修饰符,接口里的普通方法总是使用public abstract来修饰(系统自动添加)

③默认方法(带方法体)

  • 默认方法必须使用default修饰,且不能使用static修饰,故不能直接使用接口来调用
  • 定义接口里的默认方法时,不管是否使用public修饰符,接口里的默认方法总是使用public来修饰(系统自动添加)
  • 接口的默认方法其实就是实例方法,只是多了个default修饰符而已

④类方法(带方法体)

  • 类方法必须使用static修饰,且不能使用default修饰,可以直接使用接口来调用
  • 定义接口里的类方法时,不管是否使用public修饰符,接口里的默认方法总是使用public来修饰(系统自动添加)

⑤私有方法(带方法体)

  • Java9增加了私有方法,这是因为:Java8允许在接口中定义带方法体的默认方法和类方法,那么当两个默认方法(或类方法)中包含一段相同的实现逻辑时,程序必然考虑将这段实现逻辑抽取成工具方法,而工具方法时应该被隐藏的,故Java9增加了私有方法。

⑥内部类、内部接口、内部枚举

  • 接口里的内部类、内部接口、内部枚举默认采用public static来修饰(系统自动添加)

3. 接口的作用

  • 抽象类是从多个类中抽象出来的模板,如果将这种抽象进行得更彻底,那就得到了“接口”
  • 接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据和方法实现细节,它只规定这些类里必须提供哪些方法
  • 接口是从多个相似类中抽象出来的规范,接口不提供任何实现,它体现的是规范和实现分离的设计哲学
  • 接口作为系统与外界交互的窗口,它规定了实现者必须向外提供哪些服务,还规定了调用者可以调用哪些服务以及如何调用这些服务
  • 当在一个程序中使用接口时,接口是多个模块间的耦合标准;当在多个程序之间使用接口时,接口是多个程序之间的通信标准

4. 抽象类 & 接口

  • 抽象类体现的是一种模板式设计,它作为系统中多个子类的抽象父类,已经实现了系统的部分功能(那些已经提供实现的方法)
  • 接口体现的是一种规范,它是系统的“总纲”,制定了系统各模块应该遵循的标准,故一个系统的接口不应该经常改变

三、面向接口编程

1. 接口的三大用途

  • 定义引用类型变量,该变量必须引用到接口实现类的对象,该变量也可进行强制类型转换
  • 调用接口中定义的常量
  • 被实现类实现

2. 类实现接口

// 类实现接口的语法格式
[修饰符] class 类名 extends 父类 implements 接口1, 接口2...
{
}
  • 类实现接口使用implements关键字
  • 一个类可以继承一个父类,并同时实现一个或多个接口,implements部分必须放在extends部分之后
  • 类实现接口时,该类将获得接口中定义的静态常量、方法等,故可以把实现接口理解为一种特殊的继承
  • 类实现接口时,必须完全实现接口里所定义的全部抽象方法,否则,该类将保留从父接口那里继承到的抽象方法,该类也必须定义成抽象类
  • 实现接口方法时,必须使用public访问控制修饰符,因为接口里的方法都是public的,故实现类实现接口里的方法时只能使用public访问权限

3. 模拟多继承

interface Output
{
// 静态常量,系统自动添加public static final修饰符
int MAX_CACHE_LINE = 50;
} interface Product
{
// 抽象方法,系统自动添加public abstract修饰符
int getProduceTime();
} // 让Printer类实现Output和Product接口
public class Printer implements Output, Product
{
public int getProduceTime()
{
return 45;
} public static void main(String[] args)
{
// ex1:创建一个Printer对象,当成Output使用
Output o = new Printer(); // ex2:创建一个Printer对象,当成Product使用
Product p = new Printer();
System.out.println(p.getProduceTime()); // ex3:所有接口类型的引用变量都可直接赋给Object类型的变量
Object obj = p;
}
}
  • Printer类实现了Output接口和Product接口,故Printer对象既可直接赋给Output变量,也可直接赋给Product变量
  • 彷佛Printer类既是Output类的子类,也是Product类的子类,这就是Java提供的模拟多继承,通过实现多个接口可以弥补单继承的不足
  • 虽然接口不能显式继承任何类,但所有接口类型的引用变量都可直接赋给Object类型的引用变量

13. 抽象类 & 接口的更多相关文章

  1. 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait

    [源码下载] 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait 作者:webabcd 介绍速战速决 之 PHP 类基础 抽象类 接口 trait 示例1.类的相关知识点 1(基础 ...

  2. python 全栈开发,Day21(抽象类,接口类,多态,鸭子类型)

    一.昨日复习 派生方法和派生属性 super 只有在子父类拥有同名方法的时候, 想使用子类的对象调用父类的方法时,才使用super super在类内 : super().方法名(arg1,..) 指名 ...

  3. python面向对象 : 抽象类(接口类),多态,封装(私有制封装)

    一. 抽象类(接口类) 与java一样, python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类, 它的特殊之处在于只能被继承, 不能被实例化. 从设计角度去看, 如果类是从现实对 ...

  4. 【学习笔记】--- 老男孩学Python,day18 面向对象------抽象类(接口类), 多态, 封装

    抽象类,接口类 Python没有接口这个概念 抽象类(接口类): 目的是制定一个规范 要学会归一化设计,有重复的东西就要想把它们合并起来 from abc import ABCMeta, abstra ...

  5. “全栈2019”Java第一百零六章:匿名内部类与抽象类接口注意事项

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. 面向对象 继承 抽象类 接口 static 权限修饰符

    Day01 面向对象 继承 抽象类 接口 static 1.匿名对象是指创建对象时,只有创建对象的语句,却没有把对象地址值赋值给某个变量. 2.类的继承是指在一个现有类的基础上去构建一个新的类,构建出 ...

  7. python day - 19 抽象类 接口类 多态 封装

    一. 抽象类接口类即制定一个规范 特点: 1.不可被实例化. 2.规范子类当中必须事先某个方法. 3.在python中有原生实现抽象类的方法,但没有原生实现接口类的方法. 例题:制定一个规范就是,子类 ...

  8. C# 你什么让程序员寂寞成酱紫 (男生版 娱乐中学习 抽象类 接口 继承 实现方法 )

    你什么让程序员寂寞成酱紫 (男生版 娱乐中学习 抽象类 接口 继承 实现方法 )   一个家庭 相当于 一个空间,这个空间里 有 很多元素,比如 爱,爱这个抽象事物,可能有很多动作,接吻.交流,对于一 ...

  9. 面向对象的理解 抽象类&接口

    一.关于面向对象 1.什么是面向对象     在解释面向对象之前,先说说面向过程.学过C的同学都知道,C就是面向过程的一种语言.那什么是面向过程呢?比方说组装主机,对于面向过程,需要从0开始.买cpu ...

随机推荐

  1. 实战项目-用例评审-问题总结-Dotest-董浩

    实战项目-用例评审-问题总结 内部班项目用例评审,总结的问题:供大家参考!提升用例最好的方式,可以互相执行下(评审),就会明白自己的差距或者需要避免的点在哪里.(前提是会) 1)覆盖率 原型中提到的一 ...

  2. 201871010107-公海瑜《面向对象程序设计(java)》第一周学习总结

    201871010107-公海瑜<面向对象程序设计(java)>第一周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/   ...

  3. tarjan图论算法

    tarjan图论算法 标签: tarjan 图论 模板 洛谷P3387 [模板]缩点 算法:Tarjan有向图强连通分量+缩点+DAGdp 代码: #include <cstdio> #i ...

  4. angular路由事件

    Angular 4检测路由变化,可以使用router.events来监听: 支持的事件类型: NavigationStart:导航开始 NavigationEnd:导航结束 NavigationCan ...

  5. celery生产者-消费者

    Celery是一个简单,灵活,可靠的分布式系统,用于处理大量消息,同时为操作提供维护此类系统所需的工具. 它是一个任务队列,专注于实时处理,同时还支持任务调度. celery解决了什么问题: 示例一: ...

  6. ReactNative: ReactNative初始项目的结构

    一.介绍 初学RN,一切皆新.在上篇中成功地创建并运行了一个React-Native项目,这个demo的基本结构都是系统已经创建好的,开发者在此结构下完成自己的开发即可.分别用Xcode和WebSto ...

  7. RPA中房产证的 OCR 识别

    客户需求,识别一些证件内容,包括身份证.户口本.营业执照.银行卡以及房产证,前四个比较容易实现,不管是艺赛旗的 RPA 还是百度的 OCR 都有接口,直接调用即可,但是都没有房产证的 OCR 识别,只 ...

  8. 【MySQL】MySQL 8.0的SYS视图

    MySQL的SYS视图 MySQL8.0的发展越来越趋同与Oracle,为了更好的监控MySQL的一些相关指标,出现了SYS视图,用于监控. 1.MySQL版本 (root@localhost) [s ...

  9. jQuery 源码分析(十七) 事件系统模块 实例方法和便捷方法 详解

    实例方法和便捷方法是指jQuery可以直接通过链接操作的方法,是通过调用$.event上的方法(上一节介绍的底层方法)来实现的,常用的如下: on(types,selector,data,fn,one ...

  10. js获取计算机操作系统版本

    如题,想要获取当先计算机的操作系统和版本号的话,可以用如下方法. 首先,创建osversion.js文件,文件里面的代码如下 var osData = [ { name: 'Windows 2000' ...