抽象类与抽象方法

abstract : 抽象的

abstract可以用来修饰:类、方法

abstract修饰类

> 此类称为抽象类

> 抽象类不能实例化

> 抽象类中是包含构造器的,因为子类对象实例化时,需要直接或间接的调用到父类的构造器

> 抽象类中可以没有抽象方法。反之,抽象方法所在的类,一定是抽象类。

抽象方法

> 此方法即为抽象方法

> 抽象方法只有方法的声明,没有方法体

> 抽象方法其功能是确定的(通过方法的声明即可确定),只是不知道如何具体实现(体现为:没有方法体)

> 子类必须重写父类中的所有抽象方法之后,方可实例化,否则此子类仍然是一个抽象类(还有抽象方法)

public abstract class Person { //抽象类
String name;
int age; public Person(){
} public Person(String name, int age){
this.name = name;
this.age = age;
}
public abstract void eat(); //抽象方法 public void sleep(){
System.out.println("人会睡觉");
}
}
public class Student extends Person{
String school; public Student() {
} public Student(String name, int age, String school) {
super(name, age);
this.school = school;
} public void eat(){
System.out.println("学生多吃有营养的食物");
} public void sleep() {
System.out.println("学生要保证睡眠");
}
}
public class AbstractTest {
public static void main(String[] args) {
// Person p1 = new Person(); Person设置为抽象类后不可以再创建对象 Student s1 = new Student();
s1.sleep();
}
}

 abstract不能使用的场景

abstract不能修饰:  属性、构造器、代码块等

abstract不能与哪些关键字共用:(自洽)

不能用abstract修饰私有方法、静态方法、final的方法、final的类。

> 私有方法不能重写

> 避免静态方法使用此类进行调用

> final的方法不能够被重写

> final修饰的类不能有子类

模板方法设计模式(TemplateMethod)

解决的问题:

  • 当功能内部一部分实现是确定的,另一部分实现是不确定的。这时可以把不确定的部分暴露出去,让子类去实现。
  • 换句话说,在软件开发中实现一个算法时,整体步骤很固定、通用,这些步骤已经在父类中写好了。但是某些部分易变,易变的部分可以抽象出来,供不同子类实现,这就是一种模板模式。

在此我们设计了一个模板方法,用于计算代码运行的时间,这里的code可以在后续子类中重写来计算code运行所需要花费的时间。

/**
* 抽象应用案例: 模板方法的设计模式
*/
public class TemplateTest {
public static void main(String[] args) {
PrintPrimeNumber p = new PrintPrimeNumber();
p.spendTime();
}
}
abstract class Template{
//计算某段代码执行需要花费的时间
public void spendTime(){
long start = System.currentTimeMillis(); code(); long end = System.currentTimeMillis(); System.out.println("花费的时间为:" + (end -start)); } public abstract void code();
} class PrintPrimeNumber extends Template{
public void code(){
for (int i = 2; i <= 100000; i ++){
boolean isFlag = true;
for (int j = 2; j <= Math.sqrt(i); j++){
if (i % j == 0){
isFlag = false;
break;
}
}
if (isFlag){
System.out.println(i);
}
}
}
}

案例

编写工资系统,实现不同类型员工(多态)的按月发放工资。如果当月出现某个Employee对象的生日,则将该雇员的工资增加100元

实验说明:
(1)定义一个Employee类,该类包含:
private成员变量name,number,birthday,其中birthday 为MyDate类的对象;
提供必要的构造器,
abstract方法earnings(),返回工资数额:
toString()方法输出对象的name,number和birthday。

public abstract class Employee {
private String name;
private int number;
private MyDate birthday; public Employee() {
} public Employee(String name, int number, MyDate birthday) {
this.name = name;
this.number = number;
this.birthday = birthday;
} public abstract double earnings(); //抽象方法 返回工资数额 @Override
public String toString() {
return "name='" + name + "', number=" + number +
", birthday=" + birthday ;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getNumber() {
return number;
} public void setNumber(int number) {
this.number = number;
} public MyDate getBirthday() {
return birthday;
} public void setBirthday(MyDate birthday) {
this.birthday = birthday;
}
}

(2) MyDate类包含:
private成员变量year,month,day;
提供必要的构造器;
toDateString()方法返回日期对应的字符串,xxxx年xx月xx日

public class MyDate {
private int year;
private int month;
private int day; public MyDate() {
} public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
} @Override
public String toString() {
return year + "年" + month + "月" + day + "日";
} public int getYear() {
return year;
} public void setYear(int year) {
this.year = year;
} public int getMonth() {
return month;
} public void setMonth(int month) {
this.month = month;
} public int getDay() {
return day;
} public void setDay(int day) {
this.day = day;
}
}

3)定义SalariedEmployee类继承Employee类,实现按月计算工资的员工处理
该类包括: private成员变量monthlySalary;
提供必要的构造器;
实现父类的抽象方法earnings()该方法返回monthlySalary值;
toString()方法输出员工类型信息及员工的name,number,birthday。比如: SalariedEmployee[name = ' ' ,number = , birthday = xxxx年xx月xx日]

public class SalariedEmployee extends Employee{
private double monthlySalary; public SalariedEmployee() {
} public SalariedEmployee(String name, int number, MyDate birthday, double monthlySalary) {
super(name, number, birthday);
this.monthlySalary = monthlySalary;
} @Override
public double earnings() {
return monthlySalary;
} @Override
public String toString() {
return "SalariedEmployee[ " + super.toString() + "]";
} public double getMonthlySalary() {
return monthlySalary;
} public void setMonthlySalary(double monthlySalary) {
this.monthlySalary = monthlySalary;
}
}

(4)参照SalariedEmployee类定义HourlyEmployee类,实现按小时计算工资的员工处理。该类包括
private成员变量wage和hour;
提供必要的构造器;
实现父类的抽象方法earnings()该方法返回waqe*hour值;
toString0方法输出员工类型信息及员工的name, number, birthday。

public class HourlyEmployee extends Employee{
private double wage;
private int hour; public HourlyEmployee() {
} public HourlyEmployee(String name, int number, MyDate birthday, double wage, int hour) {
super(name, number, birthday);
this.wage = wage;
this.hour = hour;
} @Override
public double earnings() {
return wage * hour;
} @Override
public String toString() {
return "HourlyEmployee = [" + super.toString() + "]";
} public double getWage() {
return wage;
} public void setWage(double wage) {
this.wage = wage;
} public int getHour() {
return hour;
} public void setHour(int hour) {
this.hour = hour;
}
}

(5)定义PayrollSystem类,创建Employee变量数组并初始化,该数组存放各类员对象的引用。
利用循环结构遍历数组元素,输出各个对象的类型,name,number,birthday,以及该对象生日。
当键盘输入本月月份值时,如果本月是某个Employee对象的生日,还要输出增加工资信息。

import java.util.Scanner;
public class PayrollSystem {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
Employee[] employees = new Employee[2];
employees[0] = new SalariedEmployee("小明",10001,new MyDate(2000,12,25),3000);
employees[1] = new HourlyEmployee("小红",10002,new MyDate(2001,1,9),100,32);
System.out.println("请输入当前的月份:");
int month = scan.nextInt();
for (int i = 0; i < employees.length; i++){
System.out.println(employees[i].toString());
if (month == employees[i].getBirthday().getMonth()){
System.out.println("此月生日!!");
System.out.println("工资:" + (employees[i].earnings() + 100));
}else{
System.out.println("工资:" + employees[i].earnings());
}
}
}
}

 接口

接口的理解: 接口的本质是 契约、标准、规范。就像法律一样,制定好以后大家都要遵守

定义接口的关键字:interface

接口内部结构的说明:

> 可以声明:

  属性: 必须使用public static final修饰

  方法:jdk8之前:声明抽象方法,修饰为public abstract

     jdk8:声明静态方法、默认方法

       jdk9:声明私有方法

> 不可以声明: 构造器、代码块等

接口与类的关系 :  实现关系

格式: class A extends SuperA implements B,C{ }

A相较于SuperA来讲,叫做子类。

A相较于B,C来讲,叫做实现类。

满足此关系后,说明:

> 类可以实现多个接口。

> 类针对于接口的多实现,一定程度上就弥补了类的单继承的局限性。

> 类必须将实现的接口中的所有的抽象方法都重写(或实现),方可实例化。否则,此实现类必须声明为抽象类。

Java基础12的更多相关文章

  1. Java基础12:深入理解Class类和Object类

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  2. 【java基础 12】HashMap中是如何形成环形链表的?

    导读:经过前面的博客总结,可以知道的是,HashMap是有一个一维数组和一个链表组成,从而得知,在解决冲突问题时,hashmap选择的是链地址法.为什么HashMap会用一个数组这链表组成,当时给出的 ...

  3. Java基础12 类型转换与多态

    链接地址:http://www.cnblogs.com/vamei/archive/2013/04/01/2992662.html 作者:Vamei 出处:http://www.cnblogs.com ...

  4. java基础12 抽象类(及关键字:abstract)

    抽象类:abstract 1.应用的场景 我们描述一类事物时,存在着某种行为,但这种行为目前不具体,那么我们就可以抽取这种行为的声明,但是不去实现这种行为,我们就需要使用抽象类. 2.抽象的好处 强制 ...

  5. Java基础12 类型转换与多态(转载)

    类型检查 Java的任意变量和引用经过类型声明(type declaration),才能使用.我们之前见过对象数据.类数据.方法参数.方法返回值以及方法内部的自动变量,它们都需要声明其类型.Java是 ...

  6. Java基础12一IO流

    1.IO流的原理 利用数据通道实现程序和数据源之间数据的的读写操作.  2.IO流分类 输入流.输出流.字节流.字符流.节点流.过滤流  3.InputStream 字节输入流 实现类FileInpu ...

  7. java基础(12):构造方法、this、super

    1. 构造方法 我们对封装已经有了基本的了解,接下来我们来看一个新的问题,依然以Person为例,由于Person中的属性都被private了,外界无法直接访问属性,必须对外提供相应的set和get方 ...

  8. android基础篇------------java基础(12)(多线程操作)

    <一>基本概念理解 1.什么是进程? 进程就是在某种程度上相互隔离,独立运行的程序.一般来说,系统都是支持多进程操作的,这所谓的多进程就是让系统好像同时运行多个程序. 2.什么是线程呢? ...

  9. 2015年12月28日 Java基础系列(六)流

    2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流

  10. 050 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 12 continue语句

    050 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 12 continue语句 本文知识点:continue语句 continue语句 continue ...

随机推荐

  1. 六.黑马程序员-eclipse的使用和快捷键

    1.Eclipse的概述 A: 是一个集成开发工具,专门针对java的 B: Eclipse 免费的 开源 C: MyEclipse 收费的 具体良好的插件扩展功能,针对插件收费2.Eclipse的使 ...

  2. python爬取网站图片保存到本地文件夹

    爬取的网站 https://wallpaperscraft.com/catalog/anime 爬取代码 # 导包 import os import requests import parsel fr ...

  3. oeasy教您玩转vim - 71 - # 视图view

    ​ 视图view 回忆上次折叠的细节 折叠方式很多 我们一般就用默认的就行 indent 很好用 前提是缩进语法严格到位 这样语法和排版都能同时确保 打开关闭 zc.zo 是打开关闭当前行 zm.zr ...

  4. java web 开发框架编

    学习web 框架上开发需要的是安装  mysql 8.0  idea 2022 git  2.2.23  node 16以上 (新版本不好拉有些库了)jdk 最好是17以上 jdk8也是行的,反正不管 ...

  5. 【教程】解决npm 报错 npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead.

    问题描述 只要在控制台执行npm,不论有没有参数,都会有此警告: npm WARN config global `--global`, `--local` are deprecated. Use `- ...

  6. layui下拉框的数据如何直接从数据库提取(动态赋值)

    代码说明部分 第一步:先把layui官方给的模板粘到自己的前端注:下面的代码是我直接从layui官网粘过来的 <div class="layui-form-item"> ...

  7. 腾讯云免费申请SSL证书配置https

    证书申请 1.进入腾讯云官网,在上方直接搜索SSL,搜索到后点击立即选购: 2.点击进去后选择自定义配置,加密标准选择默认的国际标准,证书种类选择域名免费版(DV),勾选同意服务条款后选择免费快速申请 ...

  8. 【Vue2】Direct 指令

    1.内容渲染指令 1.插值表达式 2.V - TEXT 3.V - HTML <!DOCTYPE html> <html lang="en"> <he ...

  9. 【Java】逻辑错误BUG

    开局一张图来解释就够了 查询 COUNT() 结果数,有且仅有一条记录 好死不死判断查询的结果数量等等于0, 这不永远都是取TRUE返回 花了一个下午的时间就为了解决这个BUG

  10. 代码随想录Day3

    203.移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 . 示例 1: 输入:head = [1 ...