七:Java之封装、抽象、多态和继承

时间:2024-05-31 17:07:08

本文章介绍了关于Java中的面向对象封装、抽象、继承、多态特点

Java面向对象主要有四大特性:封装、抽象、继承和多态。

一、封装

封装就是将抽象得到的数据和行为(或功能)相结合,形成一个有机的总体,也就是将数据与操作数据的源码进行有机的结合,形成“类”,当中数据和函数都是类的成员。

在面向对象语言中,封装特性是由类来体现的,我们将现实生活中的一类实体定义成类,当中包括属性和行为(在Java中就是方法)。就好像人类,能够具有name,sex,age等属性,同一时候也具有eat(),sleep()等行为,我们在行为中实现一定的功能。也可操作属性,这是面向对象的封装特性.

封装隐藏了类的内部实现机制,能够在不影响使用的情况下改变类的内部结构。同一时候也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的仅仅是它的訪问方法。封装的目的是增强安全性和简化编程。使用者不必了解详细的实现细节,而仅仅是要通过 外部接口,一特定的訪问权限来使用类的成员。

二、抽象

    抽象就是将一类实体的共同特性抽象出来,封装在一个抽象类中。所以抽象在面向对象语言是由抽象类来体现的。比方鸟就是一个抽象实体。由于抽象实体并非一个真正的对象,它的属性还不能全然描写叙述一个对象,所以在语言中体现为抽象类不能实例化。

三、多态

   多态就是通过传递给父类对象引用不同的子类对象从而表现出不同的行为,多态可为程序提供更好的可扩展性,同样也能够代码重用。

程序中定义的引用变量所指向的详细类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序执行期间才确定。即一个引用变量倒底会指向哪个类的实例对象。该引用变量发出的方法调用究竟是哪个类中实现的方法,必须在由程序执行期间才干决定。由于在程序执行时才确定详细的类,这样。不用改动源程序代码,就能够让引用变量绑定到各种不同的类实现上,从而导致该引用调用的详细方法随之改变,即不改动程序代码就能够改变程序执行时所绑定的详细代码。让程序能够选择多个执行状态,这就是多态性。

     方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种 表现。重载Overloading是一个类中多态性的一种表现。假设在子类中定义某方法与其父类有同样的名称和參数,我们说该方法被重写 (Overriding)。子类的对象使用这种方法时,将调用子类中的定义。对它而言。父类中的定义如同被“屏蔽”了。假设在一个类中定义了多个同名的方 法,它们或有不同的參数个数或有不同的參数类型,则称为方法的重载(Overloading)。Overloaded的方法是能够改变返回值的类型。方法的重写Overriding和重载Overloading是Java多态性的不同表现。

  多态中的两种类型转换:

① 向上类型转换(upcast)(上转型):将子类型转换成父类型。对于向上类型转换。不须要显示指定:

Parent p = newChild();

② 向下类型转换(downcast)(下转型):将父类型转换为子类型。对于向下类型转换,必须要显示指定,使用强制类型转换:

Parent p = newChild();

Child child =(Child)p;

演示样例

<span style="font-size:18px;"><span style="font-size:18px;">//汽车接口
interface Car{
// 汽车名称
String getName(); // 获得汽车售价
int getPrice();
} // 宝马
class BMWimplements Car {
public String getName() {
return "BMW";
} public int getPrice() {
return 300000;
}
} // 奇瑞QQ
class CheryQQimplements Car {
public String getName() {
return "CheryQQ";
} public int getPrice() {
return 20000;
}
} // 汽车出售店
public classCarShop {
// 售车收入
private int money = 0; // 卖出一部车
public void sellCar(Car car) {
System.out.println("车型:" + car.getName() + " 单位价格:" +car.getPrice());
// 添加卖出车售价的收入
money += car.getPrice();
} // 售车总收入
public int getMoney() {
return money;
} public static void main(String[] args){
CarShop aShop = new CarShop();
// 卖出一辆宝马
aShop.sellCar(new BMW());
// 卖出一辆奇瑞QQ
aShop.sellCar(new CheryQQ());
System.out.println("总收入:" + aShop.getMoney());
}
} 执行结果: 车型:BMW 单位价格:300000
车型:CheryQQ 单位价格:20000
总收入:320000</span></span>

四、继承

   简单的说。继承就是在一个现有类型的基础上,通过添加新的方法或者重定义已有方法的方式,产生一个新的类型。我们在使用JAVA时编写的每个类都是在继承。由于在JAVA语言中,java.lang.Object类是全部类最根本的基类(或者叫父类、超类),假设我们新定义的一个类没有明白地指定继承自哪个基类,那么JAVA就会默觉得它是继承自Object类的。

我们能够把JAVA中的类分为以下三种:

基本类: 使用class定义且不含有抽象方法的类。也就是一般的类(一般所说的类就是基本类)。是对象的模板,是属性和方法的集合。能够继承其它基本类、抽象类、实现接口。

抽象类:使用abstract class定义的类,它能够含有,也能够不含有抽象方法。

有抽象方法的类(抽象方法就是该方法必须由继承来实现,本身仅仅定义,不实现)。

抽象类能够有一个或多个抽象方法,他是基本类和接口类的过度。

接口类:使用interface定义的类。一般叫做接口,该类中的全部方法都是抽象方法,该类的方法本身仅仅定义不实现。

抽象类和接口一个由【abstract class + 抽象类名】一个由【interface +接口名】定义。接口中的所以方法都是抽象方法,而抽象类有部分方法是自身实现了的。一些仅仅定义不实现。

在这三种类型之间存在以下的继承规律:

类能够继承(extends)类,能够继承(extends)抽象类。能够继承(implements)接口。

抽象类能够继承(extends)类,能够继承(extends)抽象类。能够继承(implements)接口。

接口仅仅能继承(extends)接口。

演示样例

<span style="font-size:18px;"><span style="font-size:18px;">public class Fruit{
public void price() {
System.out.println("水果价格");
}
public void weight() {
System.out.println("水果重量");
}
}
抽象类的定义:
public abstractclass Fruit {
public void price() {
System.out.println("水果价格");
}
public abstract void weight();
}
接口类的定义:
public interfaceFruit {
public void price();
public void weight() ;
}</span></span>

从上面我们能够看出接口就是抽象类的升级版,由于该类的方法全是抽象方法,所以把abstract换成interface。而接口的方法必须由子类才干实现。

请注意上面三条规律中每种继承情况下使用的不同的keywordextends和implements,它们是不能够任意替换的。

大家知道。一个普通类继承一个接口后,必须实现这个接口中定义的全部方法,否则就仅仅能被定义为抽象类。我在这里之所以没有对implementskeyword使用“实现”这样的说法是由于从概念上来说它也是表示一种继承关系。并且对于抽象类implements接口的情况下,它并非一定要实现这个接口定义的不论什么方法,因此使用继承的说法更为合理一些。

以上三条规律同一时候遵守以下这些约束:

类和抽象类都仅仅能最多继承一个类,或者最多继承一个抽象类,并且这两种情况是相互排斥的,也就是说它们要么继承一个类,要么继承一个抽象类。

类、抽象类和接口在继承接口时。不受数量的约束。理论上能够继承无限多个接口。当然,对于类来说。它必须实现它所继承的全部接口中定义的全部方法。

抽象类继承抽象类。或者实现接口时。能够部分、全部或者全然不实现父类抽象类的抽象(abstract)方法,或者父类接口中定义的接口。

类继承抽象类。或者实现接口时,必须全部实现父类抽象类的全部抽象(abstract)方法,或者父类接口中定义的全部接口。

继承给我们的编程带来的优点就是对原有类的复用(重用)

演示样例:

<span style="font-size:18px;"><span style="font-size:18px;">public class Sub{
private Parent p = new Parent(); public void doSomething() {
// 复用Parent类的方法
p.method();
// other code
}
} class Parent{
public void method() {
// do something here
}
}</span></span>

当然,为了使代码更加有效,我们也能够在须要使用到原有类型(比方Parent p)时。才对它进行初始化。

五、继承、接口与多态的相关问题:

1、继承的作用?优点?坏处?

继承:通过继承实现代码复用。Java中全部的类都是通过直接或间接地继程java.lang.Object类得到的。

继承而得到的类称为子类,被继承的类称为父类。子类不能继承父类中訪问权限为private的成员变量和方法。

子类能够重写父类的方法,及命名与父类同名的成员变量。

但Java不支持多重继承,即一个类从多个超类派生的能力。

优点:

a由于大部分是继承而来的,实现代码重用。降低代码书写量。

b非常easy改动和扩展已有的实现

缺点:

a打破了封装,由于基类向子类暴露了实现细节

b白盒重用,由于基类的内部细节通常对子类是可见的

c当父类的实现改变时可能要对应的对子类做出改变

d不能在执行时改变由父类继承来的实现

2、接口的优点?坏处?

优点:帮助Java语言实现一个相似于多继承的功能.可是实现的多继承功能不会使代码中的类之间出现网状关系,而是比較清楚的树状关系,相似于家谱的感觉。

缺点:假设向一个java接口添加一个新的方法时。全部实现这个接口的类都得编写详细的实现。

3、多态的作用?优点?坏处?

作用:简单的说就是一个接口。多种实现;继承的表现就是多态(没有继承就没有多态。)

a应用程序不必为每个派生类编写功能调用。仅仅须要对抽象基类进行处理就可以。

大大提高程序的可复用性。

b派生类的功能能够被基类的方法或引用变量所调用。这叫向后兼容,能够提高可扩充性和可维护性。

优点:

a可替换性(能够替换一存在的代码);

b可扩充性(添加新的子类不影响原有类的特性)。

c接口性。

d灵活性。

e简化性

缺点:a“遮盖”私有方法。仅仅有非private的方法才干够被笼罩,虽然编译器不会报错,然而也不会遵照我们所渴望的来实行。在导出类中。对于基类中的private方法,优秀採纳不同的名字。

b域在转型时候的问题。对于成员变量(域),导出类将占有从基类承袭而来的成员变量和自己的成员变量(变量名字相一同也是如此),况且。将分摊不同的存储空间。这么,导出类将具有两个名目一样的域。为了取得基类的域,务须实际地著名super.field能力走訪,而默许的域则是导出类自己的域。

c静态计策是与类相关系的。而非与某个对象相干联的,那么它就不拥有多态行动。

4、什么是重载?什么是重写?

重载:

a方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同一时候存在,具有不同的參数个数/类型。重载Overloading是一个类中多态性的一种表现。

b Java的方法重载,就是在类中能够创建多个方法,它们具有同样的名字,但具有不同的參数和不同的定义。调用方法时通过传递给它们的不同參数个数和參数类型来决定详细使用哪个方法, 这就是多态性。

c重载的时候。方法名要一样。可是參数类型和个数不一样。返回值类型能够同样也能够不同样。

无法以返回型别作为重载函数的区分标准。

重写:

a父类与子类之间的多态性。对父类的函数进行又一次定义。

假设在子类中定义某方法与其父类有同样的名称和參数。我们说该方法被重写 (Overriding)。

在Java中。子类可继承父类中的方法。而不须要又一次编写同样的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的改动。这就须要採用方法的重写。方法重写又称方法覆盖。

b若子类中的方法与父类中的某一方法具有同样的方法名、返回类型和參数表,则新方法将覆盖原有的方法。

如需父类中原有的方法,可使用superkeyword。该keyword引用了当前类的父类。

c子类函数的訪问修饰权限不能少于父类的;

5、什么是组合?

组合: 

a通过创建一个由其它对象组合的对象来获得新功能的重用方法

b新功能的获得是通过调用组合对象的功能实现的

c有时又叫聚合

优点:

a被包括对象通过包括他们的类来訪问

b黑盒重用,由于被包括对象的内部细节是不可见的

c非常好的封装

d每个类专注于一个任务

e通过获得和被包括对象的类型同样的对象引用,能够在执行时动态定义组合的方式

缺点:

a结果系统可能会包括很多其它的对象

b为了使组合时能够使用不同的对象。必须小心的定义接口