JavaSE笔记_day09_接口、继承、权限修饰符、内部类

158 阅读19分钟

一.接口

1.接口的概念

  • 接口就是多个类的公共规范

2.接口的定义 (暂且先理解为接口中的方法,都是抽象方法)

public interface MyInterface {//创建了一个接口
    //备注:换成了关键字interface之后,编译生成的字节码文件仍然是:  .java ->   .class
    public abstract void methodAbs1();//这是一个抽象方法
    public abstract void methodAbs2(int x,int y);//这是一个抽象方法
}
public abstract 返回值类型 方法名称(参数);//抽象方法无大括号
注意:
    1.接口当中的抽象方法,修饰符必须是两个固定的关键字:public abstract
    2.这两个关键字修饰符,可以选择性的省略。(今天新学,不推荐)
    3.方法的三要素可以随意定义
接口存在的意义:降低耦合度,因为接口中定义的都是抽象方法,相当于只有方法的定义,没有方法的实现,等着类去实现,体现出方法的定义和实现做分离。

3.接口的实现

  • 接口不能实例化对象(不能直接new),必须有一个"实现类"来实现该接口。
              (类与类之间的关系,叫做继承关系 extends) 
              (类与接口之间的关系,叫做实现关系 implements)

格式:
    public class 实现类名称 implements 接口名称{
        //...
    }

  • 接口的实现类重写接口中所有的抽象方法,这个类就是一个普通的类,可以实例化对象。
       实现:去掉abstract关键字,加上方法体大括号。 

       注意:如果实现类没有重写接口中所有的抽象方法,那么这个实现类继承来的抽象方法,实现类就是一个抽象类,不可实例化对象。

  • 创建实现类的对象,进行使用

public class Demo01Interface {//主程序
    public static void main(String[] args) {
    //  MyInterface inter = new MyInterface();//报错,不能直接new对象使用
        MyInterfaceImpl impl = new MyInterfaceImpl(); //创建实现类的对象使用
        impl.methodAbs1();
        impl.methodAbs2();
    }
}
public class MyInterfaceImpl implements MyInterface{//普通类实现接口
    //覆盖重写接口中所有的抽象方法
    @Override
    public void methodAbs1() {
        System.out.println("重写了第一个方法:");
    }
    @Override
    public void methodAbs2(int x ,int y) {
        System.out.println("重写了第二个方法:");
    }
}

4.接口中定义成员变量

  • 接口中定义"成员变量"但是必须使用public static final三个关键字进行修饰 从效果上看,这其实就是接口中的【常量】

public interface MyInterfaceConst {
    //公开的 静态的 不可变
    public static final int NUM_OF_MY_CLASS = 10;//这就是一个常量,一旦赋值不可以修改,永远都是10.
}		

  • 注意事项:
  1. 一旦使用final关键字,说明不可改变 
  2. 接口中的常量,可以省略public static final,不写也是这样 
  3. 接口当中的常量,必须进行赋值,不能不赋值。 
  4. 接口中常量的名称,使用完全大写的字母,用下划线进行分割。 
  5. 可用类名.调用(静态的)

public class Demo05Interface {
    public static void main(String[] args) {
        //访问接口当中的常量
         int x = MyInterfaceConst.NUM_OF_MY_CLASS;
    }
}	

5.接口中定义抽象方法 

  • 默认使用 public abstract 修饰,可以省略,但是子接口一定要写public,因为父接口为public。

6.接口中定义构造方法

7.接口中定义默认方法

格式:
    public default 返回值类型 方法名称(参数列表){
        //方法体
    }

  • 备注:接口当中的默认方法,可以解决接口升级的问题。
1.接口的默认方法,可以通过接口实现类对象,直接调用

2.接口的默认方法,也可以被接口实现类进行覆盖重写 

public class Demo02Interface {//主方法
    public static void main(String[] args) {
        MyInterfaceDefaultA a = new MyInterfaceDefaultA(); //创建了实现类A对象
        a.methodAbs();//调用抽象方法,new的是实现类A,实际运行的是实现类A的方法
        a.methodDefault(); //这是新添加的默认方法!。实现类A中没有覆盖重写methodDefault();调用默认方法,如果实现类没有,会向上找接口
        System.out.println("====================");
        MyInterfaceDefaultB b = new MyInterfaceDefaultB();
        b.methodAbs();//调用抽象方法,new的是实现类B,实际运行的是实现类B的方法
        b.methodDefault();//实现类B中覆盖重写了接口的默认方法。实现类B中覆盖重写了methodDefault();
    }
}
public interface MyInterfaceDefault {//这是一个接口
    public abstract void methodAbs();//这是一个抽象方法
    //  public abstract void methodAbs2();//这是新添加的抽象方法,避免实现类A,B都重写 ==> 新添加的方法,改成默认方法
    public default void methodDefault(){//接口中定义默认方法,实现类中不用重写了。default不能省略
        System.out.println("这是新添加的默认方法!");
    }
}
public class MyInterfaceDefaultA implements MyInterfaceDefault {//这是实现类A-实现-接口
    @Override
    public void methodAbs() {
        System.out.println("实现了抽象方法!AAA");
    }
    //实现类A中没有覆盖重写public default void methodDefault
}
public class MyInterfaceDefaultB implements MyInterfaceDefault {//这是实现类B-实现-接口
    @Override
    public void methodAbs() {
        System.out.println("实现了抽象方法!BBB");
    }
    @Override
    public void methodDefault(){//实现类B中覆盖重写了public default void methodDefault
        System.out.println("实现类B中覆盖重写了接口的默认方法");
    }
}

8.接口中定义静态方法

格式:
    public static 返回值类型 方法名称(){
        //方法体
    }

注:1.就是将abstract 或者 default 换成static即可 

       2.不能通过接口中的实现类对象来调用接口中的静态方法 

       3.通过接口名称,直接调用其中的静态方法。只能通过 接口名称.静态方法名(参数);

public class Demo03Interface {
    public static void main(String[] args) {
        //MyInterfaceStaticImpl impl = new MyInterfaceStaticImpl(); //创建了实现类对象
        //impl.methodStatic(); 错误写法
        MyInterfaceStatic.methodStatic();//正确调用   接口名称.静态方法名(参数);
    }
}
public interface MyInterfaceStatic {//这是一个接口
    public static void methodStatic(){
        System.out.println("这是接口的静态方法!");
    }
}
public class MyInterfaceStaticImpl implements MyInterfaceStatic {//这是一个实现类
}

9.接口中定义私有方法

  • 问题描述: 
       需要抽取一个公共方法,用来解决两个默认方法之间重复代码的问题。 
       但是这个共有方法,不应该让实现类使用,应该是私有化的。methodCommon应单独让1,2使用 
  • 解决方案:接口中定义私有方法:
  1. 普通私有方法:解决多个默认方法之间重复代码问题。

格式:
    private 返回值类型 方法名称(参数){
        //方法体
    }
   2.静态私有方法:解决多个静态方法之间重复代码问题。 

格式:
    private static 返回值类型 方法名称(参数){
        //方法体
    }

public class MyInterfacePrivateAImpl implements MyInterfacePrivateA {实现类A -实现- 接口A
    public void methodAnother(){
        //methodCommon();//实现类中,不能访问到了接口中的私有方法,这样是错误的。专门为了Default1和Default2来存在的
        //methodCommon();一经private修饰,程序报错
    }
}
public interface MyInterfacePrivateA {//接口A中含有默认方法1和默认方法2,两者中含有重复代码
    public default void methodDefault1(){
        System.out.println("这是一个默认方法1!");
        methodCommon();
    }
    public default void methodDefault2(){
        System.out.println("这是一个默认方法2!");
        methodCommon();
    }
    private void methodCommon(){//解决重复代码问题,只有本接口中才能访问
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }
}
============================================================================================
public class Demo04Interface {
    public static void main(String[] args) {	
        MyInterfacePrivateB.methodStatic1();//静态方法1只能通过类名.调用
        MyInterfacePrivateB.methodStatic2();//静态方法2只能通过类名.调用
    //  MyInterfacePrivateB.methodStaticCommon();错误写法,methodStaticCommon()人家是私有的
    }
}			
public interface MyInterfacePrivateB {//接口B中含有静态方法1和静态方法2,两者中含有重复代码
    public static void methodStatic1(){
        System.out.println("这是一个静态方法1!");
        methodStaticCommon();
    }
    public static void methodStatic2(){
        System.out.println("这是一个静态方法2!");
        methodStaticCommon();
    }
    private static void methodStaticCommon(){//静态私有方法,只有本接口中静态方法1和静态方法2才能访问
        System.out.println("AAA");
        System.out.println("BBB");
        System.out.println("CCC");
    }
}

10.接口小结

1.成员变量其实是常量,格式:
    [public] [static] [final] 数据类型 常量名称 = 数据值;
注意:常量必须进行赋值,而且一旦赋值不能改变。
     常量名称完全大写,用下划线进行分割。
2.接口中最重要的就是抽象方法,格式:
    [public] [abstract] 返回值类型 方法名称(参数);//无方法体
注意:实现类必须覆盖重写接口所有的抽象方法,除非实现类是抽象类。
3.接口里允许定义默认方法,格式:
    [public] default 返回值类型 方法名称(参数){ 方法体 }
注意:默认方法也可以被覆盖重写
4.接口里允许定义静态方法,格式:
    [public] static 返回值类型 方法名称(参数){ 方法体 }
注意:应该通过接口名称进行调用,不能通过实现类对象调用接口静态方法
5.接口里允许定义私有方法,格式:
    普通私有方法:private 返回值类型 方法名称(参数) {}
    静态私有方法:static private 返回值类型 方法名称(参数) {} 
注意:private的方法只有接口自己才能调用,不能被实现类或别人使用

11.继承父类并实现多个接口

使用接口注意事项:
    1.接口是没有静态代码块或者构造方法的
    2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。
    格式:
        public class MyInterfaceImpl implements MyInterfaceA , MyInterfaceB {
            //覆盖重写所有抽象方法
        }
    3.如果实现类所实现的多个接口当中,存在重复的抽象方法,只需要重写重写一次即可。
    4.如果实现类没有重写所有接口中的所有抽象方法,那么实现类就必须是一个抽象类。
    5.如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行重写。
    6.一个类如果直接父类当中的方法和接口当中的默认方法,产生了冲突,优先用父类当中的方法
public interface MyInterfaceA {//接口A
    //1.static{} 错误写法,接口不能有静态代码块
    //public MyInterface(){} 错误写法,接口不能有构造方法
    public abstract void methodA();//A中抽象方法
    public abstract void methodAbs();//A、B中都有抽象方法
    public default void methodDefault(){
        System.out.println("默认方法AAA");
    }
}
public interface MyInterfaceB {//接口B
    //static{} 错误写法,接口不能有静态代码块
    //public MyInterface(){} 错误写法,接口不能有构造方法
    public abstract void methodB();//B中抽象方法
    public abstract void methodAbs();//A、B中都有抽象方法
    public default void methodDefault(){
        System.out.println("默认方法BBB");
    }
}
public class MyInterfaceImpl /*extends Object*/ implements MyInterfaceA,MyInterfaceB { //2.实现类 -> 接口A,B
    @Override
    public void methodA() {
        System.out.println("重写了A方法");
    }
    @Override
    public void methodAbs() {//3.A、B接口都有的抽象方法,重写一次即可
        System.out.println("重写了A、B接口都有的抽象方法");
    }
    @Override
    public void methodB() {
        System.out.println("重写了B方法");
    }
    @Override
    public void methodDefault(){//接口A,B存在重复的默认方法,那么实现类一定要对冲突的默认方法进行重写。
        System.out.println("对多个接口当中冲突的默认方法进行了重写");
    }
}
==============================================================
public abstract class MyInterfaceAbstract implements MyInterfaceA , MyInterfaceB {//4.实现类没有重写所有接口中的所有抽象方法,那么实现类就必须是一个抽象类
    @Override
    public void methodA() {
    }
    @Override
    public void methodB() {
    }
}
===============================================================
public class Demo01Interface {//6.父类方法与接口方法重名,优先父类的方法
    public static void main(String[] args) {
        Zi zi = new Zi();
        zi.method();
    }
}
public class Fu {
    public void method(){
        System.out.println("父类的方法");
    }
}
public class Zi extends  Fu implements MyInterface{
}
public interface MyInterface {
    public default void method(){
        System.out.println("接口当中的默认方法");
    }
}

12.接口之间的多继承

  • 类与接口之间的关系 
  1. 类与类之间是单继承的,直接父类只有一个。 
  2. 类与接口之间是多实现的,一个类可以实现多个接口。 
  3. 接口与接口之间是多继承的 
  • 注意事项:
  1. 多个父接口当中的抽象方法如果重复,没关系。(子接口想要运行也必须定义抽象类) 
  2. 多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的重写,而且要带着default关键字。

public interface MyInterfaceA {//接口A
    public abstract void methodA();//A中特有抽象方法
    public abstract void methodCommon();//A、B接口中都有重名的抽象方法
    public default void methodDefault(){//父A、父B接口中都有重名的默认方法,
        System.out.println("AAA");
    }
}
public interface MyInterfaceB {//接口B
    public abstract void methodB();//B中特有抽象方法
    public abstract void methodCommon();//A、B接口中都有重名的抽象方法
    public default void methodDefault(){//父A、父B接口中都有重名的默认方法
        System.out.println("BBB");
    }
}
public interface MyInterface extends MyInterfaceA,MyInterfaceB {//子接口MyInterface  继承了父接口A和父接口B
    public abstract void method();
    /* 这个子接口当中有几个方法?
    *   4个
    * methodA 来源于接口A
    * methodB 来源于接口B
    * methodCommon 同时来源于A和B
    * method来源于自己
    */
    @Override
    public default void methodDefault() {//父A、父B接口中默认方法重复,那么子接口必须进行默认方法的重写
    }
}
public class MyInterfaceImpl implements MyInterface {//实现类 -实现- 接口MyInterface,四个方法
    @Override
    public void method() {
    }
    @Override
    public void methodA() {
    }
    @Override
    public void methodB() {
    }
    @Override
    public void methodCommon() {
    }
}

  • 笔记本电脑案例

案例分析:进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘
    *USB接口,包含打开设备功能、关闭设备功能
    *笔记本类,包含开机功能、关机功能、使用USB设备功能
    *鼠标类,要实现USB接口,并具备点击的方法
    *键盘类,要实现USB接口,具备敲击的方法
public class DemoMain {
    public static void main(String[] args) {
        Computer c = new Computer();
        c.powerOn();//开机
        //准备一个鼠标,创建鼠标实现类
        //使用多态写法,向上转型
        USB usbMouse = new Mouse();//左父右子,左接口右实现类
        c.useDevice(usbMouse);//参数是USB类型,编译看左,运行看右,把鼠标传进去了
========================================================
        //准备一个键盘,创建键盘实现类
        //不使用多态写法
        Keyboard keyboard = new Keyboard();
        c.useDevice(keyboard);
        /*c.useDevice(new Keyboard());匿名对象也是可以的*/
        c.powerOff();//关机
    }
}
public interface USB {//定义一个接口
    public abstract void open();//打开设备,抽象方法
    public abstract void close();//关闭设备,抽象方法
}
public class Computer {//定义一个笔记本类
    public void powerOn(){
        System.out.println("笔记本开机");
    }
    public void powerOff(){
        System.out.println("笔记本关机");
    }
    public void useDevice(USB usb ){ //使用USB设备的方法,使用接口作为方法的参数,传进来时,已经向上转型
        usb.open();//打开设备
        //要想使用鼠标、键盘实现类特有方法,必须向下转型
        if(usb instanceof Mouse){
            Mouse mouse = (Mouse)usb;//向下转型成鼠标
            mouse.click();
        }
        if (usb instanceof Keyboard){
            Keyboard keyboard = (Keyboard)usb;//向下转型成键盘
            keyboard.type();
        }
        usb.close();//关闭设备
    }
}
public class Mouse implements USB  {//鼠标实现类 -实现- USB接口
    @Override
    public void open() {
        System.out.println("打开鼠标");
    }
    @Override
    public void close() {
        System.out.println("关闭鼠标");
    }
    public void click(){
        System.out.println("鼠标点击");
    }
}
public class Keyboard implements USB  {//键盘实现类 -实现- USB接口
    @Override
    public void open() {
        System.out.println("打开键盘");
    }
    @Override
    public void close() {
        System.out.println("关闭键盘");
    }
    public void type(){
    	System.out.println("键盘输入");
    }
}

二.四种权限修饰符

* Java中有四种权限修饰符
*                    public > protected > (default) > private
* 同一个类(我自己)        √          √          √          √
* 同一个包(我邻居)        √          √          √          ×
* 不同包,继承(我儿子)    √          √          ×          ×
* 不同包,非继承(陌生人)  √          ×          ×          ×
* 注意:
*   (default) 关键字是根本不写

三.内部类

  • 定义: 如果一个事物包含另一个事物,这也就是一个类内部包含另一个类 例如:身体和心脏的关系、汽车和发动机的关系

1.成员内部类

格式:
    修饰符 class 外部类名称{
        修饰符 class 内部类名称{ }
    }

  • 注意:内用外,随意访问 ; 外用内,需要内部类对象 
  • 如何使用成员内部类? 
  1. 间接方式: 在外部类的方法当中,使用内部类 ; 然后main只是调用外部类的方法
  2. 直接方式: 
      创建普通对象:类名称 对象名 = new 类名称(); 

      创建内部类对象:外部类名称.成员内部类 对象名 = new 外部类名称().new 内部类名称();

public class Demo01InnerClass {
    public static void main(String[] args) {
        //1.间接方式 通过外部类的对象调用外部类的方法,里面间接使用内部类Heart
        Body body = new Body();//外部类的对象
        body.methodBody();//调用外部类的方法
        System.out.println("======================================================");
        //2.直接方式 外部类名称.成员内部类 对象名 = new 外部类名称().new 内部类名称
        Body.Heart heart = new Body().new Heart();
        heart.beat();
    }
}
public class Body {//外部类
    public class Heart{//成员内部类
        public void beat(){//内部类的方法
            System.out.println("心脏跳动,蹦蹦蹦!");
	    System.out.println("我叫: " + name);//正确写法
	}
    }
    private String name; //外部类的成员变量
    public void methodBody(){//外部类的方法
        System.out.println("外部类的方法!");
        //间接使用成员内部类,在外部类方法当中创建对象
        Heart heart = new Heart();
        heart.beat();
        /*new Heart().beat();也可*/
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}			

2.局部内部类 (包含匿名内部类)

  • 定义: 
      如果一个类书籍定义在一个方法内部的,那么这就是一个局部内部类。 

     "局部" :只有当前所属的方法才能使用它,出了这个方法外面就不能用了。

格式:
    修饰符 class 外部类名称{
        修饰符 返回值类型 外部类方法名称(参数){
            class 局部内部类名称{
		 
             }
        }
    }

public class DemoMain {
    public static void main(String[] args) {
        Outer obj = new Outer();
        obj.methodOuter();
    }
}
public class Outer {
    public void methodOuter(){//外部类方法
        class Inner {//局部内部类,只能在外部类方法访问
            int num = 10;
            public void methodInner() {//局部内部类方法
                System.out.println(num);//10
            }
        }
        Inner inner = new Inner();//用局部内部类创建了一个对象
        inner.methodInner();//调用局部内部类对象的成员方法
    }
}

3.内部类的同名变量访问

  • 如果发生了重名: 
  1. 内部类的局部变量 - 直接就近原则调用 
  2. 内部类的成员变量 - this.内部类成员变量名 
  3. 外部类的成员变量 - 外部类名称.this.外部类成员变量名

public class Demo02InnerClass {
    public static void main(String[] args) {
        Outer.Inner obj = new Outer().new Inner();//创建内部类对象
        obj.methodInner();//内部类方法
    }
}
public class Outer {//外部类
    int num = 10;//外部类的成员变量
    public class Inner{//内部类
        int num = 20;//内部类的成员变量
        public void methodInner(){//内部类的方法
            int num = 30;//内部类方法的局部变量
	    System.out.println(num);//局部变量30
	    System.out.println(this.num);//内部类的成员变量20
	    System.out.println(Outer.this.num);//外部类的成员变量10
	}
    }
}

4.注意事项

权限修饰符
    public > protected > (default) > private
    类的权限修饰符规则:
        1.外部类:public  / (default)
        2.成员内部类:public / protected / (default) / private
        3.局部内部类:么都不能写

5.局部内部类的final问题

  • 如果需要访问局部内部类所在方法的局部变量,那么这个局部变量必须是【有效final的】 
  • 所在方法的局部变量,必须用final关键字修饰,可省略,不可改变 
  • 原因(生命周期问题):
  1. new出来的对象在堆内存中。
  2. 局部变量跟着方法走,在栈内存中。 
  3. 方法运行结束之后,立刻出栈,局部变量就会消失。
  4. 但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。

public class MyOuter {//外部类
    public void methodOuter(){//成员方法
        final int num = 10;//所在方法的局部变量,必须用final关键字修饰,可省略,不可改变
        class MyInner {//局部内部类
            public void methodInner(){//实例化的对象时间更长,必须保证num静态的不变的
	        System.out.println(num);
	    }
        }
    }
}

6.匿名内部类

  • 定义: 如果接口的实现类(或者父类的子类),只需要使用唯一的一次 可以省略该类的定义,而改为使用【匿名内部类】   

格式:
    --直接new接口补上一个大括号重写
    接口名称 对象名 = new 接口名称(){
        //覆盖重写接口中所有抽象方法 大括号相当于作为实现类存在
    };

  • 注意事项:
  1. 匿名内部类,在创建对象时,只能使用一次 
  2. 匿名对象,在调用方法的时候,只能调用唯一一次,如果希望同一个对象,调用多次方法,那么必须给对象起个名字 
  3. 匿名内部类是省略了实现类或子类,但是匿名对象是省略了对象名称。 
   强调:匿名内部类、匿名对象不是一回事

public class DemoMain {
    public static void main(String[] args) {
    /*  MyInterfaceImpl impl = new MyInterfaceImpl();//定义一个接口实现类对象
        impl.method(); */			
    /*  MyInterface obj = new MyInterfaceImpl();//左父右子,左接口右实现类 多态方式
        obj.method();*/
        //1.使用了匿名内部类,省略了对象名称
        new MyInterface() {//大括号相当于作为实现类存在
            @Override
	    public void method1() {
	        System.out.println("实现类覆盖重写了方法!111");
	    }
            @Override
	    public void method2() {
	        System.out.println("实现类覆盖重写了方法!222");
	    }
	}.method1();
        //因为匿名对象无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象。
        //2.使用匿名内部类,多态写法,左接口右实现类
        MyInterface objA = new MyInterface() {//大括号相当于作为实现类存在
            @Override
	    public void method1() {
	        System.out.println("实现类覆盖重写了方法!111");
	    }
	    @Override
	    public void method2() {
	        System.out.println("实现类覆盖重写了方法!222");
	    }
        };
	objA.method1();
	objA.method2();
    }
}
public interface MyInterface {//接口
    public abstract void method1();//抽象方法
    public abstract void method2();//抽象方法
}
public class MyInterfaceImpl implements MyInterface {//接口实现类
    @Override
    public void method1() {
        System.out.println("实现类覆盖重写了方法!111");
    }
    @Override
    public void method2() {
        System.out.println("实现类覆盖重写了方法!222");
    }
}

四.类作为成员变量的类型

String是一个类

public class DemoMain {
    public static void main(String[] args) {
        //创建一个英雄角色
        Hero hero = new Hero();
        //为英雄起一个名字,并且设置年龄
        hero.setName("盖伦");
        hero.setAge(20);
        //创建一个武器对象
        Weapon weapon = new Weapon("多兰剑" );
        //为英雄配武器
        hero.setWeapon(weapon);
        hero.attack();//年龄为: 20的盖伦正在用多兰剑攻击水晶
    }
}
public class Hero {/*英雄角色类*/
    private String name;//英雄名字
    private int age;//英雄年龄
    private Weapon weapon;//英雄武器类 作为成员变量
    public Hero() {//英雄的无参构造
    }
    public Hero(String name, int age, Weapon weapon) {//英雄的全参构造
        this.name = name;
        this.age = age;
        this.weapon = weapon;
    }
    public void attack(){//成员方法
        System.out.println("年龄为: "+ age +"的"+name+"正在用"+weapon.getCode()+"攻击水晶");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Weapon getWeapon() {
        return weapon;
    }
    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }
}
public class Weapon {//武器类
    private String code;//武器代号
    public Weapon() {//无参构造
    }
    public Weapon(String code) {//全参构造
    	this.code = code;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
	this.code = code;
    }
}

五.接口作为成员变量类型

public class DemoGame {
    public static void main(String[] args) {
        Hero hero = new Hero();
        hero.setName("艾希");//设置英雄的名称
        //设置英雄技能
        //使用单独定义的实现类*/
     /* hero.setSkill(new SkillImpl());
        //还可以使用匿名内部类
     /* Skill skill = new Skill() {
	    @Override
	    public void use() {
	        System.out.println("pia!pia!pia!");
	    }
	};
        hero.setSkill(skill);*/
        //进一步简化,同时使用匿名内部类和匿名对象
        hero.setSkill(new Skill() {
            @Override
            public void use() {
                System.out.println("晕");
            }
        };
        hero.attack();
    }
}
public class Hero  {
    private String name;//英雄的名称
    private Skill skill;//英雄的技能
    public Hero() {//无参构造
    }
    public Hero(String name, Skill skill) {//全参构造
        this.name = name;
        this.skill = skill;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Skill getSkill() {
	return skill;
    }
    public void setSkill(Skill skill) {
        this.skill = skill;
    }
    public void attack(){
        System.out.println("我叫"+name+",开始释放技能:");
        skill.use();
        System.out.println("释放技能完成。");
    }
}
public interface Skill {//接口
    public abstract void use();//释放技能的抽象方法
}
public class SkillImpl implements Skill{//技能接口实现类
    @Override
    public void use() {
        System.out.println("biu~biu~biu~");
    }
}