首页 > 其他 > 详细

十一、接口与抽象类

时间:2020-12-27 15:35:39      阅读:41      评论:0      收藏:0      [点我收藏+]

1、类的继承

继承是面向对象的三大特征之一. 

实现继承的类被称为子类. 被继承的类被称为父类. 

Java的继承通过extends关键字实现. 

格式为:
访问控制符 [修饰符列表] class 类名 extends 父类名 {
  定义属性
  定义构造方法(super关键字)
  定义方法
}
访问控制符使用public和不使用public
修饰符列表常用的有static,final等

 在java中,继承具有以下特点:

1)只支持单继承,即一个子类只允许有一个父类。

2)子类可以拥有父类的属性和方法。

3)子类可以拥有自己的属性和方法。

4)子类可以重写覆盖父类的方法。

提示:为防止子类在想要重写父类方法时写错,造成无法覆盖,我们采用注解@Override,注解是写给编译器的注释,告诉编译器,如果下面的方法没有覆盖父类方法,则给出报错。

5)可以声明父类,创建子类(又称父类装载子类)

  例如:Person p=new Teacher();

  a) 声明什么样的类型,就只能调用什么类型的属性和方法

  b) 创建什么样的类型,就真正运行的什么类型的方法

  提示: a)和b)称为向上转型,例如:Person p=new Teacher();那么p只能打点调用Person类中的方法和属性(看到的),但实际上却运行的是创建的Teacher类型的方法。

  c) 创建什么样的类型,就可以强转为什么类型

  提示 Person p=new Teacher();t=(Teacher) p;

  这种叫做向下转型,此时t调用的是创建的Teacher类型的相应属性和方法。

继承的优点包括:

  1)提高代码复用性

  2)父类的属性方法可以用于子类

  3)可以轻松的定义子类

  4)使设计应用程序变得简单

2、Object类

Object类是一个特殊的类,是所有类的父类,如果一个类没有用extends明确指出继承于某个类,那么它默认继承Object类。

这里主要总结Object类中的几个常用方法:getClass()、toString()、equals()

2.1 getClass()方法

getClass()方法是Object定义的方法,它会返回对象执行时的Class的实例,然会使用此实例调用getName()方法可以取得类的名称。

语法:getClass().getName()

2.2 取得对象信息的方法:toString()

该方法在打印对象时被调用,将对象信息变为字符串返回,默认输出对象地址。在实际应用中通常会重写toString()方法。

public class Test1 {
    public String toString(){
        return "在"+getClass().getName()+"类中重写toString()方法";
    }
    
    public static void main(String[] args) { 
        System.out.println(new Test1());
    }
}

 输出结果:在com.test.Test1类中重写toString()方法

2.3 equals()方法

“==”比较的是两个对象的引用是否相同,而equals()方法比较的是两个对象的实际内容。

public static void main(String[] args) { 
        String s1 = "123";
        String s2 = "123";
        System.out.println(s1.equals(s2));//结果为true
        
        String v1 = new String();
        String v2 = new String();
        System.out.println(v1.equals(v2));//结果为true
        
        Demo2 d1 = new Demo2();
        Demo2 d2 = new Demo2();
        System.out.println(d1.equals(d2));//结果为false
    }

从以上实例可以看出,在自定义的类中使用equals()方法进行比较时,将返回false,因为equls()方法的默认实现是使用“==”运算符比较两个对象的引用地址,而不是比较两个对象的内容,所以要想真正做到比较两个对象的内容,需要在自定义类中重新equals()方法。

技术分享图片

3、对象类型的转换

Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。

若编译时类型和运行时类型不一致,就出现多态

//正常的方法调用(本态调用)
Person e = new Person();
e.say();
Student e = new Student();
e.say;
//虚拟方法调用(多态情况下)
Person e = new Student();
e.say(); // 调用Student类的say()方法
编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的say()方法。——动态绑定
在虚拟方法调用情况下,方法看重写后的,但属性没有重写一说,e.name为Person中的name。

引用类型之间的类型转换(对象的多态),前提:父子关系

1)向上转型

  本质:父类的引用指向了子类的对象

语法:

  父类类型 引用名 = new 子类类型();

特点:

  * 编译看左边,运行看右边

  * 可以调用父类类型中的所有成员,不能调用子类类型中特有成员;最终运行效果看子类的具体实现!

2)向下转型

语法:

  子类类型 引用名 = (子类类型)父类引用;

特点:

  ① 只能强转父类的引用,不能强转父类的对象

  ② 要求父类的引用必须指向的是当前目标类型的对象(已经指向子类类型的)

  ③ 可以调用子类类型中所有的成员

4、使用instanceof

当在程序中执行向下转型操作时,如果父类对象不是子类对象的实例,就会发生ClassCastException异常,所以在做执行向下转型之前需要养成一个良好的习惯,就是判断父类对象是否为子类对象的实例。这个判断通常使用instanceof操作符来完成。

语法格式:
myobject instanceof ExampleClass 
myobject:某类的对象引用。
ExampleClass:某个类。
使用instanceof操作符的表达式返回值为布尔值。 如果返回值为true,说明myobject对象为ExampleClass的实例对象; 如果返回值为false,说明myobject对象不是ExampleClass的实例对象。

技术分享图片

5、方法的重载

在Java中,同一个类中的多个方法可以有相同的名字,只要它们的参数列表不同就可以,这被称为方法重载(method overloading)。

说明:

  * 参数列表不同包括:个数不同、类型不同和顺序不同。

  * 仅仅参数变量名称不同是不可以的。

  * 跟成员方法一样,构造方法也可以重载。

  * 声明为final的方法不能被重载。

  * 声明为static的方法不能被重载,但是能够被再次声明。

方法的重载的规则:

  * 方法名称必须相同。

  * 参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。

  * 方法的返回类型可以相同也可以不相同。

  * 与返回值类型无关, 只看方法名和参数列表。

方法重载的实现:

  * 方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错,这叫做重载分辨。

6、多态

在java里,多态是同一个行为具有不同表现形式或形态的能力,即对象多种表现形式的体现就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。(一种事物具有不同的表现形式叫做多态。)

多态是继封装、继承之后,面向对象的第三大特性。

在Java中,通常使用方法的重载(Overloading)和重写(Overriding)实现类的多态性

7、抽象类与接口

7.1 抽象类

什么是抽象?

百度给出的解释是:从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象。

这句话概括了抽象的概念,而在Java中,你可以只给出方法的定义不去实现方法的具体事物,由子类去根据具体需求来具体实现。

这种只给出方法定义而不具体实现的方法被称为抽象方法(含有Abstract关键字开头的方法叫做抽象方法),抽象方法是没有方法体的,在代码的表达上就是没有“{}”。

原因解释:

  1) 抽象方法为什么没有方法体:

  抽象类的抽象方法需要继承它的子类来实现,如果有方法体,子类去玩吗?本来抽象类起到的类似于”模板”的作用,好比于一种参考。

  2) 抽象方法为什么abstract和static不能同时使用:

  这要探讨static修饰符的特性了,静态方法属于整个类的,静态方法只能访问静态成员变量或调用静态的成员方法。

  静态方法和静态属性可以被继承,但是没有被重写而是被隐藏。抽象类被继承后抽象方法会重写,而静态方法会被隐藏没有重写。

  包含一个或多个抽象方法的类也必须被声明为抽象类。

抽象类:简单点来说就是不能实例化的类(或者说不能用new方法实例化的类)抽象类有点类似“模板的作用,其目的是根据他的格式来创建和修改新的类。

(比如:盖房子首先有要画图纸,在照着图纸进行造房子。图纸就好比如抽象类,建房子就好比如抽象类派生的子类)

使用abstract修饰符来表示抽象方法以及抽象类。

技术分享图片

抽象类、抽象方法之间的关系

  * 含有抽象方法的类叫做抽象类,抽象类不一定还有抽象方法。

抽象类的特性

* 抽象类本能被实例化不能new,抽象方法必须在子类中被实现。

* 抽象类和抽象方法必须用关键字abstract修饰

* 抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类

* 抽象类的抽象方法abstract和static不能同时使用

* 抽象类中可以有属性, 可以存在普通方法,抽象类一定有构造方法,其目的是对属性的初始化。

* 抽象类不能用final声明(final定义的类没有子类)

* 可以直接调用抽象类中的静态方法(静态方法属于类的本身)

* 类即使不包含抽象方法,也可以被声明为抽象类,防止被实例化。

* 不能有抽象构造方法或抽象静态方法。

--- 抽象类存在的意义就是为了被子类继承

--- 抽象方法存在的意义就是必须被子类重写

注意点:

  * 一个类如果继承了抽象类,这个类必须重写抽象类的所有抽象方法

   * 只要有一个抽象方法没有被重写,子类也必须称为抽象类。

   * 一个类如果拥有了抽象方法,这个类必须定义成抽象类。

   * abstract 修饰范围:类和方法。不能修饰常量、变量。被修饰的类不能被继承,被修饰的方法不能重写。

几点说明:

  * 抽象类不能直接使用,需要子类去实现抽象类,然后使用其子类的实例。

  * 然而可以创建一个变量,其类型也是一个抽象类,并让他指向具体子类的一个实例,也就是可以使用抽象类来充当形参,实际实现类为实参,也就是多态的应用。

在下列情况下,一个类将成为抽象类:

* 当一个类的一个或多个方法是抽象方法时。

* 当类是一个抽象类的子类,并且不能实现父类的所有抽象方法时。

* 当一个类实现一个接口,并且不能实现接口的所有抽象方法时。

注意:

* 上面说的是这些情况下一个类将称为抽象类,没有说抽象类就一定会是这些情况。

* 抽象类可以不包含抽象方法,包含抽象方法的类就一定是抽象类。

* 事实上,抽象类可以是一个完全正常实现的类。

抽象类的几个小问题

A:抽象类有构造方法,不能实例化,那么构造方法有什么用?

-- 用于子类访问父类数据的初始化

B:一个类没有抽象方法,能否定义为抽象类?如果可以,有什么意义?

-- 可以的。抽象类中不一定有抽象方法

--意义:不让其类创建实例,交由子类完成。

C:abstract不能和哪些关键字共存?

* abstract和static,被abstract修饰的方法没有方法体,被static修饰的可以用类名调用,类名.抽象方法是没有意义的。

* abstract和final,被abstract修饰的方法,在子类中要强制重写,被final修饰的方法,在子类中不能重写,所以二者是矛盾的。

* abstract和private,被abstract修饰的是为了让子类看到并强制重写,被private修饰的是不让自类访问,所以他俩也是矛盾的。

7.2 接口

定义接口

接口继承和实现继承的规则不同,一个类只有一个直接父类,但可以实现多个接口。

Java 接口本身没有任何实现,只描述 public 行为,因此 Java 接口比 Java 抽象类更抽象化。

Java 接口的方法只能是抽象的和公开的,Java 接口不能有构造方法,Java 接口可以有 public、Static 和 final 属性。

* 接口中只有抽象方法

* 接口不能被实例化

* 接口中所有的成员属性都是public final static 

* 接口不能有构造方法

语法格式
【修饰符】
interface 接口名 {   【访问权限修饰符】 【static】 【final】 数据类型 常量名 = 值;   【访问权限修饰符】 abstracr 方法名(); }

接口对于其声明、变量和方法都做了许多限制,这些限制作为接口的特征归纳如下:

  * 具有 public 访问控制符的接口,允许任何类使用;

  * 没有指定 public 的接口,其访问将局限于所属的包。

技术分享图片

接口中常量的说明:

* 在接口中只能声明常量;

* 访问权限修饰符、static、final 都可以省略的,省略后JVM还会默认为是public static final属性的(在代码中还是建议都写上);所以接口中定义的变量必须初始化。

* 访问权限修饰符只能是public,即使省略,也依然是public。

接口中方法的说明:

* 接口中的抽象方法的访问权限修饰符只能是public,即便省略,也依然是public;

* 接口中只能有抽象方法;(JDK1.7之前)

* 接口中没有构造方法。

总结:

  接口中只有静态常量和抽象方法。

实现接口

接口被定义后,一个或者多个类都可以实现该接口,这需要在实现接口的类的定义中包含 implements 子句,然后实现由接口定义的方法。

实现接口的一般形式如下:

【修饰符】 class 类名 extends 父类名 implements 接口列表 {类体}

语法:

interface 子接口 extends 父接口1,父接口2,父接口3……

类实现接口的特点

* 类最多只能继承一个类,即单继承;

* 而一个类可以同时实现多个接口,多个接口间用逗号隔开即可

* 实现类需要覆盖所有接口中的抽象方法,否则该类必须声明为抽象类。

总结

1)类与类、类与接口、接口与接口的关系?

类与类:继承关系,只能是单继承,可以多层继承。

类与接口:实现关系,可以单实现,也可以多实现,并且还可以在继承一个类的同时,再实现多个接口

接口与接口:继承关系,可以单继承,也可以多继承.

2)抽象类与接口的区别?

A:成员的区别

抽象类:

成员变量:可以是变量,也可以是常量

构造方法:有

成员方法:可以有抽象方法,也可以有非抽象方法

接口

成员变量:只可以是常量,接口中所有的属性全都是public final static

构造方法:没有

成员方法:只可以有抽象方法

B:设计理念的区别

抽象类:被继承的,“is a”的关系。抽象类中定义的是该继承体系的共性功能。

接口:被实现,“like a”的关系。接口中定义的是该继承体系的扩展功能。

C:抽象类只能被继承,而且只能单继承。接口需要被实现 ,而且多实现

D:抽象类可以有构造方法,但是接口没有构造方法。

共同点:都不能被实例化,接口比抽象更严谨

十一、接口与抽象类

原文:https://www.cnblogs.com/ljk-shm-0208/p/14039537.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!