Java学习第四章(一)

视频链接:https://www.bilibili.com/video/BV1Rx411876f?p=1

视频范围P465 - P525

1.super关键字

1.1 super概念

  1. super是一个关键字,全部小写
  2. super和this对比着学习
    this
    ①this能出现在实例方法和构造方法中
    ②this的语法是:“this.”、“this()”
    ③this不能使用在静态方法中
    ④this.大部分情况下是可以省略的
    ⑤this.什么时候不能省略呢?
    答:在区分局部变量和实例变量的时候不能省略,如:
    public void setName(String name){ this.name = name; }
    ⑥this()只能出现在构造方法第一行,通过当前的构造方法去调用"本类"中的其它的构造方法,目的是:代码复用
    super
    ①super能出现在实例方法和构造方法中
    ②super的语法是:“super.”、“super()”
    ③super不能使用在静态方法中
    ④super.大部分情况下是可以省略的
    ⑤super.什么时候不能省略呢?
    答:父类和子类中有同名属性,或者说有同样的方法。想在子类中访问父类的,super.不能省略。
    ⑥super()只能出现在构造方法第一行,通过当前的构造方法去调用"父类"中的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。
  3. super()
    表示通过子类的构造方法调用父类的构造方法,模拟现实世界中的这种场景:要想有儿子,需要先有父亲
  4. 重要结论:当一个构造方法第一行:
    既没有this()又没有super()的话,默认会有一个super();表示通过当前子类的构造方法调用父类的无参数构造方法,所以必须保证父类的无参数构造方法是存在的
  5. 注意:this()和super()不能共存,它们都是只能出现在构造方法第一行
  6. 无论是怎么折腾,父类的构造方法是一定会执行的

1.2 代码实例一

package Super;


public class SuperTest01 {
	
	public static void main(String[] args) {
		
		//创建子类对象
		new B();
	}
}

class A extends Object{//自动继承
	
	//建议手动的将一个类的无参数构造方法写出来
	public A() {
		//super();//这里也是默认有这一行代码
		System.out.println("A类的无参数构造方法!");
	}
	
	//一个类如果没有手动提供任何构造方法,系统会默认提供一个无参构造方法
	//一个类如果手动提供了一个构造方法,那么无参数构造系统将不再提供
	public A(int i) {
		//super();
		System.out.println("A类的有参数构造方法(int)!");
	}
}

class B extends A{
	
	public B() {
		this("zhangsan");
		//调用父类中有参数的构造方法
		//super(123);
		System.out.println("B类的无参数构造方法!");
	}
	
    public B(String name) {
		super();
		System.out.println("B类的有参数构造方法!(String)");
	}
}

运行结果

在这里插入图片描述

1.3 代码实例二

  1. 在java语言中不管是new什么对象,最后老祖宗的Object类的无参数构造方法一定会执行
  2. Object类的无参数构造方法是处于"栈顶部"
  3. 栈顶的特定:最后调用,但是最先执行结束;后进先出原则
  4. 以后写代码的时候,一个类的无参数构造方法还是建议大家手动的写出来。如果无参数构造方法丢失的话,可能会影响到“子类对象的构建”。
package Super;

public class SuperTest02 {

	public static void main(String[] args) {
		new C();
	}
}

class A extends Object{
	public A() {
		super();
		System.out.println("1");
	}
}

class B extends A {
	public B() {
		System.out.println("2");
	}

	public B(String name) {
		System.out.println("3");
	}
}

class C extends B {
	public C() {//这个是最先调用,但是最后结束
		this("zhangsan");
		System.out.println("4");
	}

	public C(String name) {
		this(name, 20);
		System.out.println("5");
	}

	public C(String name, int age) {
		super(name);
		System.out.println("6");
	}
}

运行结果

在这里插入图片描述

1.4 代码实例三

  1. 在恰当的时间使用:super(实际参数列表);
  2. 注意:在构造方法执行过程中一连串调用了父类的构造方法,父类的构造方法又继续向下调用它的父类的构造方法,但是实际上对象只创建了一个
  3. super(实参)的作用:初始化当前对象的父类型特征,并不是创建新对象,实际上对象只创建了1个
  4. super关键字代表的是“当前对象”的那部分父类型特征
    例如:我基础了我父亲的一部分特征,如眼睛和皮肤
    super代表的就是眼睛和皮肤,“眼睛和皮肤”虽然是继承了父亲的,但这部分是在我身上的

账户类

package Super;

public class Account {
	
	//属性
	private String actno;
	private double balance;
	
	//构造方法
	public Account() {
	     //super();//不写默认会有的
	    //this.actno =  null //默认会有的
	    //this.balance = 0.0 //默认会有的
	}

	public Account(String actno, double balance) {
		this.actno = actno;
		this.balance = balance;
	}

	public String getActno() {
		return actno;
	}

	public void setActno(String actno) {
		this.actno = actno;
	}

	public double getBalance() {
		return balance;
	}

	public void setBalance(double balance) {
		this.balance = balance;
	}
}

信用账户

package Super;

public class CreditAccount extends Account {
	
	//属性:信誉度/诚信度
	//子类特有的一个特征,父类没有
	private double credit;
	
	//无参的构造方法
	public CreditAccount() {
	    super();//不写默认会有的
	    //this.credit = 0.0 //默认会有的
	}
	
	//带参的构造方法
	public CreditAccount(String actno,double balance,double credit) {
		
		//私有属性,只能在本类中访问
		//this.actno = actno;
		//this.balance = balance;
		
		//以上两行代码在恰当的位置,正好可以使用:super(actno,balance);
		//通过子类的构造方法调用父类的构造方法
		super(actno,balance);
		this.credit = credit;
	}

	public double getCredit() {
		return credit;
	}

	public void setCredit(double credit) {
		this.credit = credit;
	}
}

测试类

package Super;

public class SuperTest03 {

	public static void main(String[] args) {
		
		CreditAccount ca1 = new CreditAccount();
		System.out.println(ca1.getActno() + "," + ca1.getBalance() + "," + ca1.getCredit());//输出为:null,0.0,0.0
		CreditAccount ca2 = new CreditAccount("111",1000.0,0.999);
		System.out.println(ca2.getActno() + "," + ca2.getBalance() + "," + ca2.getCredit());//输出为:111,1000.0,0.999
	}
}

内存分析图

在这里插入图片描述

1.5 代码实例四

顾客类

package Super;

public class Customer {
	
	String name;

	public Customer() {

	}

	public Customer(String name) {
		this.name = name;
	}	
}

贵宾类

package Super;

public class Vip extends Customer {

	public Vip() {
		
	}
	
	public Vip(String name) {
		super(name);
	}
	
	//super和this都不能出现在静态方法中
	public void shopping() {
		//this表示当前对象
		System.out.println(this.name + "正在购物!");
		//super表示的是当前对象的父类型特征。(super是this指向的那个对象中的一块空间)
		System.out.println(super.name + "正在购物!");
		System.out.println(name + "正在购物!");//此处的name等价于this.name,只是this.可以省略
	}
}

测试类

package Super;

public class SuperTest04 {

	public static void main(String[] args) {
		
		Vip v = new Vip("张三");
		v.shopping();
	}
}

运行结果
在这里插入图片描述

内存分析图
在这里插入图片描述

1.6 代码实例五

  1. java中允许在子类中出现和父类一样的同名变量/同名属性
  2. “this.”和“super.”大部分情况下都是可以省略的
  3. this.什么时候不能省略?
public void setName(String name){
    this.name = name;
}
  1. super.什么时候不能省略?
    父中有,子中又有,如果想在子中访问“父的特征”,super.不能省略
  2. java是怎么来区分子类和父类的同名属性的?
    this.name :当前对象的name属性
    super.name:当前对象的父类型特征中的name属性

顾客类

package Super;

public class Customer {
	
	String name;

	public Customer() {

	}

	public Customer(String name) {
		super();
		this.name = name;
	}
	
	public void doSome() {
		
		System.out.println(this.name + "do some!");
		System.out.println(name + "do some!");
		//错误:找不到符号,父类中没有name属性
		//System.out.println(super.name + "do some!");
	}
}

贵宾类

package Super;

public class Vip extends Customer {

    //假设子类也有一个同名属性
    String name;//实例变量
    
	public Vip() {
		
	}
	
	public Vip(String name) {
		super(name);
		this.name = null; //不写,默认也会有的
	}
	
	//super和this都不能出现在静态方法中
	public void shopping() {
		//this表示当前对象
		System.out.println(this.name + "正在购物!");
		//super表示的是当前对象的父类型特征。(super是this指向的那个对象中的一块空间)
		System.out.println(super.name + "正在购物!");
		System.out.println(name + "正在购物!");//此处的name等价于this.name,只是this.可以省略
	}
}

测试类

package Super;

public class SuperTest05 {

	public static void main(String[] args) {
		
		Vip v = new Vip("张三");
		v.shopping();
	}
}

运行结果

在这里插入图片描述
内存分析图
在这里插入图片描述

1.7 代码实例六

  1. super不是引用,也不保存内存地址,也不指向任何对象
  2. super只是代表当前对象内部的那一块父类型的特征
  3. this和super不能使用在static静态方法中,只能用在实例方法中
package Super;

public class SuperTest06 {
	
	//实例方法
	public void doSome() {
		
		//输出“引用”的时候,会自动调用引用的toString()方法
		//下面中的this和this.toString()是一样的!!!
		System.out.println(this);//输出为:Super.SuperTest06@7de26db8
		System.out.println(this.toString());//输出为:Super.SuperTest06@7de26db8
		
		//编译错误:需要'.'
		//System.out.println(super);
	}
	
	//this和super不能使用在static静态方法中,只能用在实例方法中
	/*
	 * public static void doOther() {
	 * 
	 * System.out.println(this); 
	 * System.out.println(super.xxx);
	 * 
	 * }
	 */
	
	//静态方法,主方法
	public static void main(String[] args) {
		
		SuperTest06 st = new SuperTest06();
		st.doSome();
	}
}

1.8 代码实例七

  1. 在父和子中有同名的属性,或者说有相同的方法,如果此时想在子类中访问父中的数据,必须使用“super.”加以区分
  2. super.属性名【访问父类的属性】
  3. super.方法名(实参)【访问父类的方法】
  4. super(实参)【访问父类的构造方法】

动物类

package Super;

public class Animal {
	public void move() {
		System.out.println("Animal move!");
	}
}

猫类

package Super;

public class Cat extends Animal {
	
	//对move进行重写
	public void move() {
		System.out.println("Cat move!");
	}
	
	//单独编写一个子类特有的方法
	public void yidong() {
		this.move();
		move();
		//super.不仅可以访问属性,也可以访问方法
		super.move();
	}
}

测试类

package Super;

public class SuperTest07 {

	public static void main(String[] args) {
		
		Cat c = new Cat();
		c.yidong();
	}
}

运行结果
在这里插入图片描述

2.IDEA工具

关于java的集成开发环境:eclipse、IntelliJ IDEA等
目前主流的集成开发环境是:IntelliJ IDEA
注意:IDEA是自动保存,不需要ctrl + s

2.1 IDEA工具的使用

步骤如下

  1. 第一次打开的时候,会弹出一个窗口(import idea settings),这个表示导入idea的设置,但我们是第一次使用idea工具,没有设置过idea,所以选择 :do not import setting…不导入设置
  2. 接受条款
  3. don’t send
  4. 一直下一步(最终选择免费试用30天)
  5. 可能会让你填写email等信息,这里不填写,继续continue
  6. 弹出welcome窗口
    点击create new project
    注意:在IDEA当中一个project相当于eclipse当中的一个workspace
  7. 新建一个Empty Proiect
    新建一个空的工程,选择创建工程窗口下面“最后的那一项”,Empty Proiect
  8. 给空的工程起一个名字:javase
    存储到:C:\Users…
    点击finish
  9. 自动弹出一个每日提示,这个每日提示可以取消掉,以后每一次打开就不再提示
  10. 会自动弹出一个:project structure,这个窗口先取消掉
  11. 在空的工程下新建Module(模块),IDEA中模块类似于eclipse当中的project
    eclipse的组织方式:workspace—>project
    idea的组织方式:project—>module
    疑问:怎么创建module?
    答:file菜单—>new—>Module
  12. 在New Module窗口上点击左上角的java,然后next
  13. 给module起一个名字:chapter
  14. 编写代码,在src目录下新建类,写代码,并运行

2.2 IDEA字体设置

file—>settings—>输入font—>设置字体样式以及字号大小

2.3 IDEA快捷键

快捷键备注
psvm快速生成main方法
sout快速生成System.out.println()
ctrl + y删除一行
上下箭头左侧窗口中的列表展开和关闭
esc退出任何窗口
alt + insert任何新增/新建/添加
ctrl + shift + F12窗口变大变小
alt + 右箭头/左箭头切换java程序
ctrl + shift + F10快速运行程序
alt + 标号(1,2,3,…)切换窗口
ctrl + P提示方法的参数
Home光标回到头
End光标回到尾
ctrl + /单行注释
ctrl + shift + /多行注释
按住ctrl + 点击单词定位方法/属性/变量
ctrl + d复制一行
alt + 回车纠正错误
ctrl + F12查看一个类的属性和方法

3.抽象类

3.1 抽象类概念

  1. 概念:类和类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类
  2. 类本身是不存在的,所以抽象类无法创建对象《无法实例化》
  3. 抽象类和抽象类实际上可能还有共同特征,还可以进一步再抽象
  4. 抽象类也属于引用数据类型
  5. 抽象类定义语法:
[修饰符列表] abstract class 类名{
      类体;
}
  1. 抽象类是无法实例化的,无法创建对象的,所以抽象类是用来被子类继承的
  2. final和abstract不能联合使用,这两个关键字是对立的
  3. 抽象类的子类还可以是抽象类,也可以是非抽象类
  4. 抽象类虽然无法实例化,但是抽象类有构造方法,这个构造方法是供子类使用的

示例代码

package Abstract;

public class AbstractTest01 {

	public static void main(String[] args) {
		
		//错误:Account是抽象的,无法实例化
		//Account act = new Account();
	}
}

//非法组合
/*
 * final abstract class Account{
 * 
 * }
 */

abstract class Account{
	
}

class CreditAccount extends Account{
	public CreditAccount(){
		super();
	}
}
//子类继承抽象类,子类可以实例化对象
/*
 * class CreditAccount extends Account{
 * 
 * }
 */

抽象类与类与对象的关系说明图
在这里插入图片描述

3.2 代码实训

一个非抽象的类继承抽象类必须将抽象类中的抽象方法实现了(这是java语法上强行规定的,必须的,不然编译器就报错了)
:这里的实现,也可以叫做覆盖或者重写

动物类(抽象类)

public abstract class Animal{
     public abstract void move();
}

子类(非抽象)

public class Bird extends Animal{
     //把抽象的方法实现了
     public void move(){
            System.out.println("鸟儿在飞翔!!!");
      }
}

子类(抽象)

public abstract class Maotouying extends Animal{
}

:如果子类是抽象类的,那么这个Animal中继承过来的抽象方法也可以不去重写/覆盖/实现

测试类

public class AbstractTest02{
    public static void main(String[] args){
          //使用多态,父类型指向子类型对象
          Animal a = new Bird();//面向抽象编程
          a.move();//编译的时候move()方法是Animal的,运行的时候move()方法是Bird的
   }
}

3.3 抽象方法概念

抽象类关联到一个概念:抽象方法
概念:没有实现的方法,没有方法体的方法,如:

public abstract void doSome();

抽象类特点

  1. 没有方法体,以分号结尾
  2. 前面修饰符列表中有abstract关键字

注意

  1. 抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
  2. Java语言中凡是没有方法体的方法都是抽象方法【错】
    原因:Object类中就有很多方法都没有方法体,都是以“;”结尾的,但是都不是抽象方法
    如:public native int hashCode();
    这个方法底层调用了C++写的动态链接程序,前面修饰符列表中没有:abstract。有一个native,表示调用JVM本地程序。

4.接口

4.1 接口的基础语法

  1. 接口也是一种引用数据类型,编译之后也是一个class字节码文件
  2. 接口是完全抽象的
  3. 接口定义语法
[修饰符列表] interface 接口名{}
  1. 接口支持多继承,一个接口可以继承多个接口
  2. 接口中只包含两部分内容:常量 + 抽象方法
  3. 接口中所有的元素都是public修饰的(都是公开的)
  4. 接口中的抽象方法定义时:public abstract 修饰符可以省略
  5. 接口中的常量的public static final可以省略
  6. 接口中的方法都是抽象方法,所以接口中的方法不能有方法体
  7. 一个非抽象的类,实现接口的时候,必须将接口中所有方法加以实现
  8. 一个类可以实现多个接口
  9. extends和implements可以共存,extends在前,implement在后
  10. 使用接口,写代码的时候,可以使用多态(父类型引用指向子类型对象)

代码示例

package Test;

public class Test01 {

	public static void main(String[] args) {
		
		//访问接口的常量
		System.out.println(MyMath.PI);//输出为:3.1415926
		
		//错误:无法为最终变量PI分配值
		//MyMath.PI = 3.1415928;

	}

}

interface A{
	
}

interface B extends A{
	
}

interface C extends A, B{
	
}

//我的数学接口
interface MyMath{
	//定义常量
	public static final double PI = 3.1415926;
	
	//public static final可以省略
	double PI_a = 3.1415926;
	
	//抽象方法
	public abstract int sum1(int a, int b);
	
	//接口当中既然都是抽象方法,那么在编写代码的时候,public abstract可以省略
	int sum2(int a, int b);
	
	//错误:接口抽象方法不能带有主体
	/*
	 * void doSome() {
	 * 
	 * }
	 */
}

4.2 类和接口之间的实现注意

  1. 类和类之间叫做继承,类和接口之间叫做实现
    仍可以将“实现”看做“继承”
    继承使用extends关键字完成
    实现使用implements关键字完成
  2. 当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现(覆盖、重写)
package Test;

interface MyMath_wo{
	double PI = 3.1415926;
	int sum(int a, int b );
	int sub(int a, int b );
}

//编写一个类(这个类是一个“非抽象”的类)
class MyMathImpl implements MyMath_wo{
	
	//错误:正在尝试分配更低的访问权限,以前为public
	/*
	 * int sum1(int a, int b ) 
	 * { return a + b; }
	 */
	//重写/覆盖/实现 接口中的方法(通常叫做实现)
	public  int sum(int a, int b ) {
		return a + b;
	}
	
	public  int sub(int a, int b ) {
		return a - b;
	}
}

4.3 接口和多态联合使用

package Test;

public class Test02{
	public static void main(String[] args) {
		
		//错误:MyMath_wo是抽象的;无法实例化
		//new MyMath_wo();
		
		//父类型的引用指向子类型的对象
		MyMath_wo mm = new MyMathImpl();
		//调用接口里面的方法(面向接口编程)
		int result1 = mm.sum(10, 20);
		System.out.println(result1);//输出为:30
		
		int result2 = mm.sub(20, 10);
		System.out.println(result2);//输出为:10
	}
}
interface MyMath_wo{
	double PI = 3.1415926;
	int sum(int a, int b );
	int sub(int a, int b );
}

//编写一个类(这个类是一个“非抽象”的类)
class MyMathImpl implements MyMath_wo{
	
	//错误:正在尝试分配更低的访问权限,以前为public
	/*
	 * int sum1(int a, int b ) 
	 * { return a + b; }
	 */
	//重写/覆盖/实现 接口中的方法(通常叫做实现)
	public  int sum(int a, int b ) {
		return a + b;
	}
	
	public  int sub(int a, int b ) {
		return a - b;
	}
}

4.4 一个类实现多个接口

  1. 一个类可以同时实现多个接口,这种机制弥补了Java中单继承带来的缺陷(Java中类和类只支持单继承,单继承是为了简单而出现的)
  2. 接口A和接口B虽然没有继承关系,但是写代码的时候,可以互转【编译器不报错,但是运行的时候可能出现:ClassCastException】
  3. 无论是向上转型还是向下转型,两种类型之间必须要有继承关系,没用继承关系编译器会报错【但这句话不适用在接口方面】
  4. 接口进行互转的时候还是需要加:instanceof运算符进行判断

代码示例一

package Test;

public class Test03 {

	public static void main(String[] args) {
		
		//多态的使用,父类型引用指向子类型对象
		A a = new D();
		B b = new D();
		C c = new D();
		
		//编译报错:A接口中没用m2()方法
		//a.m2();
		
		//这个编译没问题,运行也没问题
		B b2 = (B)a;
		b2.m2();//输出为:lalalalala
		
		//直接向下转型,这个编译没问题,运行也没问题
		D d = (D)a;
		d.m2();//输出为:lalalalala
	}

}

interface A{
	void m1();
}
interface B{
	void m2();
}
interface C{
	void m3();
}

//实现多个接口,类似于多继承
class D implements A,B,C{
	//实现A接口的m1()
	public void m1() {
		
	}
	//实现B接口的m2()
	public void m2() {
		System.out.println("lalalalala");
	}
	//实现C接口的m3()
    public void m3() {
		
	}
}

代码示例二

接口和接口之间在进行强制类型转换的时候,没有继承关系,也可以强转,但是运行的时候可能会出现ClassCastException错误,所以还是用instanceof运算符进行判断。

package Test;

public class Test03 {

	public static void main(String[] args) {
		
		M m = new E();
		
		if (m instanceof K) {
			K k = (K)m;
		}else {
			System.out.println("太遗憾了!");
		}
	}

}

interface K{
	
}
interface M{
	
}

class E implements M{
	
}

运行结果

在这里插入图片描述

总结:接口之间没有继承关系也可以强转,但是在实际操作中没有必要,同时也不要这样做!!!

4.5 继承和实现都存在的情况

语法结果

class A extends B implements C{
}

代码示例

package Test;

public class Test04 {

	public static void main(String[] args) {
		
		//调用同一个fly()方法,最后的执行效果不同
		//多态,创建对象(表面看Animal类没起作用!)
		Flyable f = new Cat();
		f.fly();//输出为:小猫起飞!!!
		
		//同一个接口
		Flyable f1 = new Pig();
		f1.fly();//输出为:小猪起飞!!!
		
		//同一个接口
		Flyable f2 = new Fish();
		f2.fly();//输出为:小鱼起飞!!!
	}

}

//动物类:父类
class Animal{
	
}

//接口:飞翔
//接口通常提取的是行为动作
interface Flyable{
	void fly();
}

//动物类子类:猫类
class Cat extends Animal implements Flyable{
	public void fly() {
		System.out.println("小猫起飞!!!");
	}
}

//动物类子类:朱类
class Pig extends Animal implements Flyable{
	public void fly() {
		System.out.println("小猪起飞!!!");
	}
}

//鱼类
//没写extends,也是有的,默认继承Object
/*
 1. class Fish implements Flyable{ 
 2. public void fly() {
 3.   System.out.println("小鱼起飞!!!"); } 
 4.  }
 */
class Fish extends Object implements Flyable{
	public void fly() {
		System.out.println("小鱼起飞!!!");
	}
}

4.6 接口在开发中的作用

  1. 接口在开发中的作用,类似于多态在开发中的作用
    多态:面向抽象编程,不要面向具体编程, 降低程序的耦合度,提高程序的扩展力
  2. 面向抽象编程可以改为:面向接口编程
  3. 接口是一个抽象性的概念,扩展性好
  4. 面向接口编程,可以降低程序的耦合度,提高程序的扩展力,符合OCP开发原则
  5. 接口的使用离不开多态(接口+多态才可以达到降低耦合度)
  6. 任何一个接口都有调用者和实现者,调用者面向接口调用,实现者面向接口编写实现
  7. 接口可以将调用者和实现者解耦合

菜单接口

package Interface;

public interface FoodMenu {
	
	//西红柿炒蛋
	void shiZiChaoJiDan();
	
	//鱼香肉丝
	void yuXiangRouSi();
}

中餐厨师

package Interface;

public class ChinaCooker implements FoodMenu{

	public void shiZiChaoJiDan() {
		System.out.println("中餐厨师做的西红柿炒鸡蛋!!!");
	}

	public void yuXiangRouSi() {
		System.out.println("中餐厨师做的鱼香肉丝!!!");
	}	
}

西餐厨师

package Interface;

public class AmericCooker implements FoodMenu {

	public void shiZiChaoJiDan() {
		System.out.println("西餐厨师做的西红柿炒鸡蛋!!!");
	}

	public void yuXiangRouSi() {
		System.out.println("西餐厨师做的鱼香肉丝!!!");
	}
}

顾客

package Interface;

public class Customer {
	// 如果一下这么写,就写死了,顾客只能吃中餐或者是西餐了
	// ChinaCooker cc;
	// AmericCooker ac;

	// 顾客手中有一个菜单 Customer has a FoodMenu!
	// 注意:使用has a来描述,统一以属性的方式存在:实例变量,属性
	// 面向抽象编程,面向接口编程,降低程序的耦合度,提高程序的扩展力
	private FoodMenu foodMenu;// 都要养成封装的好习惯
	
	//构造方法
	public Customer() {
		super();
	}

	public Customer(FoodMenu foodMenu) {
		this.foodMenu = foodMenu;
	}
	
	//setter and getter
	public FoodMenu getFoodMenu() {
		return foodMenu;
	}

	public void setFoodMenu(FoodMenu foodMenu) {
		this.foodMenu = foodMenu;
	}

    //提供一个点菜的方法
    public void order(){
        //先拿到菜单才能点菜
        //调用get方法拿菜单
        //FoodMenu fm = this.getFoodMenu();
        //也可以不调用get方法,因为在本类中私有的属性是考研访问
        foodMenu.shiZiChaoJiDan();
        foodMenu.yuXiangRouSi();
    }	
}

测试类

package Interface;

public class Test {

	public static void main(String[] args) {
		
		//创建厨师对象
		FoodMenu cooker1 = new ChinaCooker();
		
		//创建顾客对象
		Customer customer = new Customer(cooker1);
		
		//顾客点菜
		customer.order();
	}
}

运行结果

在这里插入图片描述

4.7 is a、has a、like a

类型举例意义代码
is aCat is a Animal(猫是一个动物)凡是能够满足is a的表示“继承关系”A extends B
has aI has a Pen(我有一支笔)凡是能够满足has a关系的表示“关联关系”,关联关系通常以“属性”的形式存在A{B b;}
like aCooker like a FoodMenu(厨师像一个菜单一样)凡是能够满足like a关系的表示“实现关系”,实现关系通常是:类实现接口A implements B

5.抽象类和接口有什么区别

这里只说在语法上的区别

  1. 抽象类是半抽象的,接口是完全抽象的
  2. 抽象类有构造方法,接口中没有构造方法
  3. 接口和接口之间支持多继承,类和类之间只能单继承
  4. 一个类可以同时实现多个接口,一个抽象类只能继承一个类(单继承)
  5. 接口中只允许出现常量和抽象方法
  6. 接口一般都是对“行为”的抽象

注意:以后接口使用的比抽象类多,一般抽象类使用的还是少

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值