Java学习笔记day12-接口-多态

Day12

接口

​ 当一个类中的所有方法都是抽象方法的时候,我们就可以将其定义为接口;接口也是一种引用数据类型,他比抽象类还要抽象;

  • 接口存在的两个重要意义
    1. 规则的定义
    2. 程序的扩展性
接口的定义和特点
  • 接口用关键字interface来定义
    • public interface 接口名{}
  • 接口不能实例化
  • 接口和类之间是实现关系,通过implements关键字表示
    • public class 类名 implements 接口名{}
  • 接口的子类(实现类)
    • 要么重写接口中的所有抽象方法
    • 要么是抽象类
  • 注意:接口和类的实现关系,可以单实现,也可以多实现。
    • public class 类名 implements 接口名1,接口名2{}

示例:

​ 给所有的动物制定两个规范,(1)所有的动物必须能吃饭;(void eat()),(2)所有的动物必须能睡觉(void sleep());已知猫和狗两个类都遵循了上面的规范,请使用代码描述出猫类和狗类,并编写测试类,创建猫类和狗类的对象,调用吃饭和睡觉的方法;

接口Animal.java

package animal;

public interface Animal {
    public abstract void eat();
    public abstract void sleep();
}

实现类Dog.java

package animal;

public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("狗吃狗粮");
    }

    @Override
    public void sleep() {
        System.out.println("狗在门口睡觉");
    }
}

实现类Cat.java

package animal;

public class Cat implements Animal {
    @Override
    public void eat() {
        System.out.println("猫吃小鱼干");
    }

    @Override
    public void sleep() {
        System.out.println("猫趴在草垛上睡觉");
    }
}

测试类

package animal;

public class AnimalTest {
    public static void main(String[] args) {
        Dog d = new Dog();
        Cat c = new Cat();
        d.eat();
        d.sleep();
        c.eat();
        c.sleep();
    }
}

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

接口中成员的特点
  • 成员变量:只能是常量,系统会默认加入三个关键字:public、static、final
  • 构造方法:没有
  • 成员方法:只能是抽象方法,系统会默认加入两个关键字:public、abstract
JDK8版本中接口成员的特点
  • JDK8版本后
    • 允许在接口中定义非抽象方法,但是需要使用关键字default修饰,这些方法就是默认方法(作用:解决接口升级问题)
    • 接口中默认方法的定义格式:
      • 格式:public default 返回值类型 方法名(参数列表){}
      • 范例:public default void show(){}
    • 接口中默认方法的注意事项:
      • 默认方法不是抽象方法,所以不强制被重写。但是可以被重写,重写的时候去掉default关键字
      • public可以省略,default不能省略
      • 如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写
    • 接口中允许定义static静态方法
    • 接口中静态方法的定义格式:
      • 格式:public static 返回值类型 方法名(参数列表){}
      • 范例:public static void show(){}
    • 接口中静态方法的注意事项:
      • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
      • public可以省略,static不能省略

示例:

接口A

package jdk8;

public interface InterA {
    public default void show(){
        System.out.println("这里是接口A");
    }
    public static void show1(){
        System.out.println("InterA...show");
    }
}

接口B

package jdk8;

public interface InterB {
    public default void show(){
        System.out.println("这里是接口B");
    }
    public static void show1(){
        System.out.println("InterB...show");
    }
}

测试类

package jdk8;

public class Test {
    public static void main(String[] args) {
        Inter1Impl i1 = new Inter1Impl();
        i1.show();
        Inter2Impl i2 = new Inter2Impl();
        i2.show();
        //i2.show1();
        InterA.show1();
        InterB.show1();
    }
}
class Inter1Impl implements InterA,InterB{

    @Override
    public void show() {
        System.out.println("这里是实现类");
    }
}
class Inter2Impl implements InterA{

}

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

接口的使用思路
  • 若发现一个类中所有的方法都是抽象方法,那么就可以将该类改进为一个接口
  • 涉及到接口大面积更新方法,不想去修改每一个实现类,就可以将更新的方法,定义为带有方法体的默认方法
  • 希望默认方法调用的更加简洁,可以考虑设计为static静态方法。(需要去掉default关键字)
  • 默认方法中出现了重复的代码,可以考虑抽取出一个私有方法。(需要去掉default关键字)
类和接口的关系
  • 类和类的关系
    • 继承关系,只能单继承,但是可以多层继承
  • 类和接口的关系
    • 实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 接口和接口的关系
    • 继承关系,可以单继承,也可以多继承
多态
概述

​ 同一个对象,在不同时刻表现出来的不同形态;

多态的前提和体现

  • 有继承/实现关系
  • 有方法重写
  • 有父类引用指向子类对象
多态中成员访问特点
  • 构造方法:同继承一样,子类会通过super访问父类构造方法
  • 成员变量:编译看左边(父类),执行看左边(父类)
  • 成员方法:编译看左边(父类),执行看右边(子类)
  • 成员方法和成员变量访问不一样的原因:
    • 成员方法有重写,而成员变量没有

示例:

package duotai;

public class DuotaiTest {
    public static void main(String[] args) {
        Fu f = new Zi();//形成多态
        System.out.println(f.num);
        f.show();
    }
}
class Fu{
    int num=10;
    public void show(){
        System.out.println("show...fu");
    }
}
class Zi extends Fu{
    int num=20;
    public void show(){
        System.out.println("show...zi");
    }
}

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

多态的好处和弊端
  • 好处:提高了程序的扩展性
    • 具体体现:定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的任意子类对象
  • 弊端:不能使用子类的特有功能;

示例:

package duotai;

public class DuotaiTest1 {
    public static void main(String[] args) {
        useAnimal(new Dog());
        useAnimal(new Cat());
    }
    public static void useAnimal(Animal a){  //Animal a = new Dog(),Animal a = new Cat()
        a.eat();
        //a.watchHome();//多态弊端,不能调用子类特有的方法
    }
}
abstract class Animal{
    public abstract void eat();
}
class Dog extends Animal{

    @Override
    public void eat() {
        System.out.println("够吃肉");
    }
    public void watchHome(){
        System.out.println("狗子看家");
    }
}
class Cat extends Animal{
    public void eat(){
        System.out.println("猫吃鱼");
    }
}

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

多态中的转型
  • 向上转型:父类引用指向子类对象
  • 向下转型:父类引用转为子类对象
多态中转型存在的风险
  • 概述:如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
  • 关键字instanceof
  • 使用格式:变量名 instanceof 类型
    • 判断关键字左边的变量是否是右边的类型,返回boolean类型结果

示例:

package duotai;

public class DuoTest2 {
    public static void main(String[] args) {
        useAnimal(new Dog1());
        useAnimal(new Cat1());
    }
    public static void useAnimal(Animal1 a){
        a.eat();
        //Dog1 d = (Dog1)a;
        //d.watchHome();//此处报错ClassCastException
        if (a instanceof Dog1){
            Dog1 d = (Dog1)a;
            d.watchHome();
        }
    }
}
abstract class Animal1{
    public abstract void eat();
}
class Dog1 extends Animal1{
    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }
    public void watchHome(){
        System.out.println("看门");
    }
}
class Cat1 extends Animal1{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}

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

练习1

1.请定义“员工(类)”:
属性:姓名、性别、年龄(全部私有)
行为:工作(抽象)
无参、全参构造方法
get/set方法
2.请定义“绘画(接口)”
抽象方法:绘画
3.请定义“Java讲师类”继承自“员工类”
4.请定义”UI讲师类”,继承自“员工类”,并实现“绘画”接口。

要求:
请按上述要求设计出类结构,并实现相关的方法,并进行调用测试。

员工类Yuangong.Java

package lian1;

public abstract class Yuangong {
    private String name;
    private String gender;
    private int age;
    public abstract void work();

    public Yuangong(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

    public Yuangong() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

绘画接口Huihua.java

package lian1;

public interface Huihua {
    public abstract void hua();
}

Java讲师类JavaTeacher.java

package lian1;

public class JavaTeacher extends Yuangong {
    @Override
    public void work() {
        System.out.println(getAge()+"岁的"+getGender()+"老师"+getName()+"正在给学生上Java课程");
    }

    public JavaTeacher(String name, String gender, int age) {
        super(name, gender, age);
    }

    public JavaTeacher() {
    }
}

UI讲师类UITeacher.java

package lian1;

public class UITeacher extends Yuangong implements Huihua {
    @Override
    public void work() {
        System.out.print(getAge()+"岁的"+getGender()+"老师"+getName()+"正在给学生上UI课程,");
    }

    @Override
    public void hua() {
        System.out.println("并在UI课上教学生绘画");
    }

    public UITeacher(String name, String gender, int age) {
        super(name, gender, age);
    }

    public UITeacher() {
    }
}

测试类Test.java

package lian1;

public class Test {
    public static void main(String[] args) {
        JavaTeacher jt = new JavaTeacher("贾玉","男",31);
        jt.work();
        UITeacher ut = new UITeacher("林玉","女",28);
        ut.work();
        ut.hua();
    }
}

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

练习2

请模拟生活中"养殖场老板指挥员工饲养动物"的场景;员工类中包含饲养动物的方法,而老板类(就是测试类)可以面向员工对象调用员工类的方法;代码关系示意图如下:
在这里插入图片描述

创建动物类Animal,定义抽象方法eat

package lian1;

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

创建Dog、Cat、Pig类继承Animal类,重写eat方法

package lian1;

public class Dog extends Animal{

    @Override
    public void eat() {
        System.out.println("狗子吃狗粮。");
    }
}
package lian1;

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫猫吃小鱼干。");
    }
}

package lian1;

public class Pig extends Animal {
    @Override
    public void eat() {
        System.out.println("小猪吃饲料。");
    }
}

创建员工类Worker,定义饲养动物的方法raiseAnimal

package lian1;

public class Worker {
    //将动物父类作为形式参数,方法可以接收任意子类动物
    public void raiseAnimal(Animal a){
        a.eat();
    }
}

创建老板类Boss,在该类中进幼崽即创建指定动物对象,并安排员工饲养动物,即调用raiseAnimal方法;

package lian1;

public class Boss {
    public static void main(String[] args) {
        Worker w = new Worker();
        Dog d = new Dog();
        Cat c = new Cat();
        Pig p = new Pig();
        //调用方法将指定动物作为实际参数传递过去
        w.raiseAnimal(d); //相当于Animal a = new Dog();父类引用指向子类对象
        w.raiseAnimal(c);
        w.raiseAnimal(p);
    }
}

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

练习3

按照要求完成以下内容:

  1. 已知电脑类(Computer), 有开机和关机的功能,以及使用鼠标和键盘的功能;
  2. 已知鼠标类(Mouse), 也有连接电脑和断开电脑的功能,connet():打印鼠标连接了;disconnet():打印鼠标断开了;
  3. 已知键盘类(Keyboard), 也有连接电脑和断开电脑的功能,connet():打印键盘连接了;disconnet():打印键盘断开了;

总结,只要是符合USB设备的东可以连接电脑和断开电脑的功能。

请编写测试类, 测试电脑开机, 电脑使用鼠标, 电脑使用键盘, 电脑关机的功能。

创建USB接口并定义connect和disconnect方法

package lian2;

public interface USB {
    public abstract void connect();
    public abstract void disconnect();
}

创建鼠标类Mouse,实现接口中的方法

package lian2;

public class Mouse implements USB {
    @Override
    public void connect() {
        System.out.println("鼠标连接了...");
    }

    @Override
    public void disconnect() {
        System.out.println("鼠标断开了...");
    }
}

创建键盘类Keyboard,实现接口中的方法

package lian2;

public class Keyboard implements USB {
    @Override
    public void connect() {
        System.out.println("键盘连接了...");
    }

    @Override
    public void disconnect() {
        System.out.println("键盘断开了...");
    }
}

创建电脑类Computer,定义使用USB接口的方法,将USB对象作为形式参数

package lian2;

public class Computer {
    public void open(){
        System.out.println("电脑开机了...");
    }
    public void close(){
        System.out.println("电脑关机了...");
    }
    public void useUSBConnect(USB usb){
        usb.connect();
    }
    public void useUSBDisconnect(USB usb){
        usb.disconnect();
    }
}

创建测试类Test,类中创建电脑、键盘、鼠标对象,并将三个对象作为方法的实际参数

package lian2;

public class Test {
    public static void main(String[] args) {
        Computer c = new Computer();
        Mouse m = new Mouse();
        Keyboard k = new Keyboard();
        c.open();
        c.useUSBConnect(m);
        c.useUSBConnect(k);
        c.useUSBDisconnect(m);
        c.useUSBDisconnect(k);
        c.close();
    }
}

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JS API 接口接收与返回 是一个轻型的、安全的、跨网际的、跨语言的、跨平台的、跨环境的、跨域的、支持复杂对象传输的、支持引用参数传递的、支持内容输出重定向的、支持分级错误处理的、支持会话的、面向服务的高性能远程过程调用协议。 该版本直接解压后就可以使用,其中 属于公共文件。不论是客户端还是服务器端都需要这些文件。 是客户端文件,如果你只需要使用客户端,那么只要有上面那些公共文件和这个文件就可以使用了,使用时,直接在你的程序中包含 phprpc_client.php 就可以,公共文件不需要单独包含。 这三个文件是服务器端需要的文件。 其中 dhparams 目录中包含的是加密传输时用来生成密钥的参数 dhparams.php 是用来读取 dhparams 目录中文件的。 phprpc_server.php 是服务器端,如果你要使用 PHP 来发布 PHPRPC 服务,只需要包含这个文件就可以了。公共文件和 dhparams.php 都不需要单独包含。 PHP 4.3+、PHP 5、PHP 6 客户端要求开启 socket 扩展。 服务器端需要有 IIS、Apache、lighttpd 等可以运行 PHP 程序的 Web 服务器。 如果服务器端需要加密传输的能力,必须要保证 session 配置正确。 <?php include('php/phprpc_server.php'); //加载文件 function hello($name) { return'Hello ' . $name; } $server = new PHPRPC_Server(); //创建服务端 $server->add(array('hello', 'md5', 'sha1')); //数组形式一次注册多个函数 $server->add('trim'); //单一注册 $server->start(); //开启服务 ?> <?php include ("php/phprpc_client.php"); //加载文件 $client = new PHPRPC_Client('http://127.0.0.1/server.php'); //创建客户端 并连接服务端文件 echo$client->Hello("word"); //调用方法 返回 hello word ?> -------------------------------------------------- --------------------------------------------------- ------------------------------ 服务端其他说明: <?php include('php/phprpc_server.php'); //加载文件 function hello($name) { return'Hello ' . $name; } class Example1 { staticfunction foo() { return'foo'; } function bar() { return'bar'; } } $server = new PHPRPC_Server(); //创建服务端 $server->add('foo', 'Example1'); //静态方法直接调用 $server->add('bar', new Example1()); //非静态方法 需要实例化 //注册别名调用 $server->add('hello', NULL, 'hi'); //第三参数是函数的别名 客户端通过别名来调用函数 $server->add('foo', 'Example1', 'ex1_foo'); $server->add('bar', new Example1(), 'ex1_bar'); $server->setCharset('UTF-8'); //设置编码 $server->setDebugMode(true); //打印错误 $server->setEnableGZIP(true); //启动压缩输出虽然可以让传输的数据量减少,但是它会占用更多的内存和 CPU,因此它默认是关闭的。 $server->start(); //开启服务 ?> -------------------------------------------------- --------------------------------------------------- --------------------------- 客户端其他说明: <?php include ("php/phprpc_client.php"); $client = new PHPRPC_Client(); $client->useService('http://127.0.0.1/server.php'); //远程调用地址 $client->setKeyLength(1000); //密钥长度 $client->setEncryptMode(3); //加密等级0-3 $client->setCharset('UTF-8'); //设置编码 $client->setTimeout(10); //设置超时时间 echo$client->hi('PHPRPC'), "\r\n"; //调用函数 echo$client->getKeyLength(), "\r\n"; //下面是返回值 echo$client->getEncryptMode(), "\r\n"; echo$client->getCharset(), "\r\n"; echo$client->getTimeout(), "\r\n"; ?> -------------------------------------------------- --------------------------------------------------- ---------------------- 关于session <?php include('php/phprpc_server.php'); class ExampleCounter { function ExampleCounter() { if (!isset($_SESSION['count'])) { $_SESSION['count'] = 0; } } function inc() { $_SESSION['count'] += 1; } functioncount() { return$_SESSION['count']; } } $server = new PHPRPC_Server(); $server->add(array('inc', 'count'), new ExampleCounter()); $server->start(); ?> <?php include("php/phprpc_client.php"); $client = newPHPRPC_Client(); $client->useService('http://127.0.0.1/1.php'); $client->setTimeout(10); echo $client->inc(); echo $client->count(); echo $client->inc(); echo $client->count(); ?> 每次刷新都是新建的client 服务端并不能识别.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值