2021.07.10 Java学习笔记之多态和接口

多态

         就是一种的事物的多种形态或则多种表达形式,多态的最终体现是父类的引用指向子类对对象(如果Person 是 Students的父类 那么  Person p  =  new Students())。他的实现基于类的继承或者接口的实现.

        如果要想多态有意义,那么就要配合重写

        多态的实现效果  :配合方法的重写,当父类引用指向不同的子类对象,同一个方法具有不同的实现方式。 

多态的调用

        父类的引用调用 

                是成员变量时:

                        编译运行看父类 | 左边 | 类型

                是成员方法时:

                        编译运行看父类 | 左边 | 类型

                        运行找子类 | 右边 | 对象

        注意: 多态是行为的多态    如果多态不配合方法的重写,那么就没有意义 ,且父类的引用对子类中的新增内容不可见 

public class Class002_Test {
    public static void main(String[] args) {
        //父类引用指向子类对象
        Fu fu = new Zi();

        System.out.println(fu.name);

        fu.test();

    }
}

class Fu{
    String name = "Fu";
    public void test(){
        System.out.println("Fu");
    }
}

class Zi extends Fu{
    String name = "Zi";

    public void test(){
        System.out.println("Zi");
    }

    //新增内容
    public void test2(){
        System.out.println("Zi2");
    }
}

下面是一个小测试

 

*
 * 做题四大原则:
 * 一、继承链:自己没有找父
 * 		A
 * 		|
 * 		B
 * 	 /    \
 *  C	   D
 * 二、 编译看类型、确定方法,运行找对象
 * 
 * 三、就近最优原则
 * 
 * 四、父类引用对子类新增方法不可见
 *
 * 编译期间能够确定所调用的方法
 */

public class Class003_PolyTest {
	public static void main(String[] args) {
		A a1=new A();  // 可以使用的方法: 
		//多态调用
		A a2=new B();  //  可以使用的方法:
		B b =new B();  //  可以使用的方法:
		C c=new C();
		D d =new D();	
		System.out.println(a1.show(b)); //结果:
		System.out.println(a1.show(c)); //结果:
		System.out.println(a1.show(d)); //结果:
		System.out.println(a2.show(b)); //结果:
		System.out.println(a2.show(c)); //结果:
		System.out.println(a2.show(d)); //结果:
		System.out.println(b.show(b));  //结果:
		System.out.println(b.show(c));  //结果:
		System.out.println(b.show(d));  //结果:
	}

}

class A{
	public String show(D obj){
		return ("A and D");
	}
	public String show(A obj){
		return ("A and A");
	}
}

class B extends A{
	//新增方法
	public String show(B obj){
		return ("B and B");
	}
	//重写方法
	@Override
	public String show(A obj){
		return ("B and A");
	}
}

class C extends B{
}

class D extends B{
}

A and D  A and A  

A and D  B and A

B and B  B and A  A and D

A and A

A and A

A and D

B and A

B and A

A and D

B and B

B and B

A and D

转型问题

        在之前我们学习过基本类型的数据转换,那么引用数据类型有数据转换吗?    

                Java 转型问题其实并不复杂,只要记住一句话:父类引用指向子类对象。

                可以分为向上转型(upcasting) 、向下转型(downcasting)

向上转型

通俗地讲即是将子类对象转为父类对象。此处父类对象可以是接口。

        Person p = new Student();

向下转型(强制类型转换)

与向上转型相反,即是把父类对象转为子类对象。

        Student s = (Student)p;

       当我们进行向下转型的时候,可能会出现 ClassCastException 类型转换异常(引用强转类型的时候,没有转为指向的子类对象类型,转为了其他子类类型,出现的异常)

        为了预防这个问题我们可以使用instanceof 运算符

        引用 instanceof 类型:
        判断前面的引用是否指向后面类型的对象或者后面类型子类的对象,是->true  不是->false

例如

public class Class001_Cast {
    public static void main(String[] args) {
        //多态
        Person p = new Student();

        //需求: 调用子类中独有的study
        //向下转型  从父类引用转为对应类型的子类引用,就可以调用子类中的所有内容

        if(p instanceof Teacher){
            Teacher s = (Teacher)p;
            s.study();
        }else if(p instanceof Student){
            Student s = (Student)p;
            s.study();
        }

        System.out.println(p instanceof Person);  //true
        System.out.println(p instanceof Object);  //true
        System.out.println(p instanceof Student); //true
        System.out.println(p instanceof Teacher); //false

    }
}

class  Person{}

class Student extends Person{
    void study(){
        System.out.println("学习");
    }
}

class Teacher extends Person{
    void study(){
        System.out.println("老师学习!!!!");
    }
}

 抽象abstract

        抽象可以分为 抽象类(被abstract修饰的类)和抽象方法(被abstract修饰的方法)

                抽象方法 :没有方法体,存在于抽象类中

                 抽象类的特点:1. 不能被实例化 

                                          2. 抽象类可以定义任意内容(属性,功能(抽象的方法,具体的方法))

                                          3. 抽象方法必须要求被重写

                                          4. 抽象类的使用: 通过具体子类对象使用

                                                     具体子类: 重写所有的抽象方法 + 按需要新增方法

                                                     抽象子类: 按照需要重写抽象方法 + 按需新增方法

                                          5.  一个抽象方法一旦被重写后,就不能在被重写,可以按照自己需求决定

                                          6. abstract 不能和 pricate、final、static 、native 一起使用

                                          7. 抽象类可以实现多态

public class Class001_Abstract {
    public static void main(String[] args) {
        //Develop d = new Develop();

        //具体子类对象
        Develop java = new Java();
        java.work();
        java.sleep();
        //java.mr();
    }
}

//父类
abstract class Develop {
    //方法体: 不知道怎么写,不知道写什么
    public abstract void work();

    //具体方法
    public void sleep(){
        System.out.println("胡吃海喝!!!!");
    }
}

//子类
class Java  extends Develop{

    @Override
    public void work() {
        System.out.println("服务器端开发");
    }

    //新增功能
    public void mr(){
        System.out.println("与测试,产品,谈论...探讨...");
    }
}

//抽象子类
abstract class Web extends Develop{
    //public abstract void work();
    public void haha(){
        System.out.println("每天哈哈傻笑...");
    }
}

接口

        接口可以理解为一个特殊的抽象类 ,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

        接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

        除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

        接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

        接口可以帮助定义规范 ,还可以解耦(降低耦合度)       

        类和接口的区别: 类是单继承,接口是多实现的 

jdk7及之前:
            公共的静态的常量
                public static final--> 修饰符可以任意省略
            公共的抽象的方法
                public abstract --> 修饰符可以任意省略

jdk8及之后:
         jdk8中新增:
        1.静态方法 : 可以定义方法体
          使用: 通过接口名使用

        2.默认方法 : 可以定义方法体
           显示的被default修饰
           使用: 通过实现类对象使用

        1.接口不能实例化
        2.接口需要通过实现类的对象使用
        3.父类需要通过子类继承  extends  -->父类中的成员,子类继承父类有权可以直接使用
                  接口需要通过实现类去实现  implements --> 因为接口中几乎都是抽象方法没有方法体,需要实现类自己实现方法体,所有叫做实现
                  接口的实现与类的继承很像,都拥有了父类的成员使用权,或者拥有接口中定义的功能,但是一个侧重点在拿过来就用,一个侧重点在拿过来要实现才能用
        4. 接口的使用:
                    具体的实现类 : 重写所有的冲向方法 + 按需新增
                    抽象的实现类 : 按需重写 + 按需新增
        5.接口可以多实现,类只能单继承
        6.如果一个类同时继承父类实现接口,要求先继承后实现 

public class Class001_Interface {
    public static void main(String[] args) {
        System.out.println(MyInterface.PI);

        //根据具体的实现类的对象使用
        MyImpl my = new MyImpl();
        my.test1();
        my.test1();
        my.haha();

    }

}

//接口
interface MyInterface{
    //公共的静态的常量
    double PI = 3.14;

    //公共的抽象的方法
    public abstract void test1();
    void test2();
}
interface A{
    void a();
}
interface B{
    void b();
}

//具体实现类
class MyImpl  extends Object implements MyInterface,A,B {

    @Override
    public void test1() {

    }

    @Override
    public void test2() {

    }
    //新增内容
    public void haha(){}

    @Override
    public void a() {

    }

    @Override
    public void b() {

    }
}

//抽象实现类
abstract class MyImpl2 implements MyInterface{
    @Override
    public void test1() {

    }
}

 注意:

        1.父类与接口无法完全相互代替,如果可以建议使用接口,因为接口可以多实现非常灵活
        2.类与类之间只能继承
                  类与接口之间,只能是类实现接口
                  类与类之间只能单继承
                  类与接口之间可以多实现
                  接口与接口之间,可以多继承

        3.接口可以实现多态  接口引用指向实现类对象

 

// jdk8中的不同点
public class Class003_Inteface {
    public static void main(String[] args) {
        Swim.test();
        //实现类对象
        new SwimImpl().test2();
    }
}

interface Swim{
    void swimming();

    //静态方法
    public static void test(){
        System.out.println("静态方法");
    }

    //默认方法
    public default void test2(){
        System.out.println("默认方法");
    }
}

class SwimImpl implements Swim{
    @Override
    public void swimming() {

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值