java学习笔记6——封装、继承和多态

java是一种面出现对象的编程语言,他的三个最重要的特性就是封装,继承和多态。
这里大致介绍一下,有个了解,想要详细学习的可以去查看一下《think in java》这本书,或者上网学习。

一、封装

  封装是把过程和数据包围起来,对数据的访问只能通过已定义的接口。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。封装是一种信息隐藏技术,在java中通过关键字private,protected和public实现封装。什么是封装?封装把对象的所有组成部分组合在一起,封装定义程序如何引用对象的数据,封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。
  适当的封装可以让程式码更容易理解和维护,也加强了程式码的安全性。

以上应用了百度百科的概念

  或许有点官方,那么用自己的话是怎么理解封装的呢?我是这么理解的:
  上一篇讲到了对象,方法和类。那么封装,其实就是把各种属性,各种方法进行一个整合,打包成类。用代码举个例子:

public class FengZhuang {
  private int i;
  private int j;
  public int getI() {
    return i;
  }
  public void setI(int i) {
    this.i = i;
  }
  public int getJ() {
    return j;
  }
  public void setJ(int j) {
    this.j = j;
  }
  public void test(String string) {
    System.out.println(string);
  }
}

  上述是一个包含了属性,set和get方法,还有一个test方法的类,封装的概念,就是将这些属于FengZhuang的属性和方法全部都写在这个类的下面,那么,如果我要调用,就可以如下所示:

public class Demo {
  public static void main(String[] args) {
    FengZhuang.test("123");
  }
}

  在其他的类中,就可以直接用 类名.方法名进行调用了。这就是封装,把属性,方法进行整合到一个类(对象)中。
封装的作用体现在:
1. 对象的数据封装特性彻底消除了传统结构方法中数据与操作分离所带来的种种问题,提高了程序的可复用性和可维护性,降低了程序员保持数据与操作内容的负担。
2 . 对象的数据封装特性还可以把对象的私有数据和公共数据分离开,保护了私有数据,减少了可能的模块间干扰,达到降低程序复杂性、提高可控性的目的
  上述的是比较官方的说法,大家理解就好。

二、继承

  Java继承是面向对象的最显著的一个特征。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
还是先看一段代码:

public class GirlFriend {
  private int age;
  private String name;
  private String address;
  private BoyFriend boyFriend;
}
public class BoyFriend {
  private int age;
  private String name;
  private String address;
  private GirlFriend girlFriend;
}

  如上述代码,有两个对象,分别是男朋友和女朋友,我们可以发现,除了男女朋友那个属性不一样,其他的都是一样的,那么,如果我们还有其他的人要写,比如,好朋友(BestFriend),那是不是又要重复写一遍年龄,姓名和地址。这个时候,就引入继承的概念,让我们把这些共有的信息拿出来:

public class PeopleInfo {
  private int age;
  private String name;
  private String address;
}

建立一个人物信息的类,然后使用extends进行继承

public class GirlFriend extends PeopleInfo {
  private BoyFriend boyFriend;
}
public class BoyFriend extends PeopleInfo {
  private GirlFriend girlFriend;
}

  这样写GirlFriend 和BoyFriend,那么只要在这个对象里面写他们特有的属性就行,但是在使用的时候,这个age等基本属性依旧是存在于GirlFriend 和BoyFriend中的。在这里,PeopleInfo 是父类,BoyFriend 是子类。
  口语化一点,继承就是在原有的类的基础上建立出来的新的类,新类的定义可以增加新的数据或者新的功能(方法),也可以使用父类的方法。
在使用继承时,要了解这三句话:
1. 子类拥有父类非private的属性和方法。
2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
3. 子类可以用自己的方式实现父类的方法。
第三句就是方法的重写,大家看下面代码

public class Father {
  public static void talk() {
    System.out.println("我是爸爸,我会说话");
  }
}
public class Child extends Father {
  public static void talk() {
    System.out.println("我是儿子,我会说话");
  }
  public static void main(String[] args) {
    talk();  
  }
}

运行结果:

我是儿子,我会说话

  看代码,在father类中已经有了talk方法,而child类继承了father方法,又重新写了一个talk的方法,这个方法就会按照child里面定义的方式进行改写。在这里,child把father里面的方法用自己的方式去实现了。这就是第三点说的,子类可以用在自己方式去实现父类的方法。这就是方法的重写。

在这里有一个特殊的存在:构造方法
构造器而言,它只能够被调用,而不能被继承。所以构造器方法也不能被重写

这里有一个概念:上溯造型
  上述代码,peopleinfo和boyfriend为例,boyfriend继承了peopleinfo,可以说是peopleinfo的一个子类,也可以说boyfriend是peopleinfo的一种,这就是一种上溯造型的概念。再打个比方,猫是动物,它具有动物所有的性质,但是在动物之上,猫还有自己的个性,那么,就可以说,猫是动物的上溯造型。
比如我们每天在使用的

    List<String> list = new ArrayList<>();
    Map<String, String> map = new HashMap<>();

这就是一个上溯造型的过程。
其实还有一个下塑造性,有兴趣的同学可以了解一下,这是一个不安全的造型。
继承虽然是java的一个特性,但是还是有缺陷:
1. 父类改变,子类必须改变。
2. 继承会破坏封装,父类的方法对子类来说是透明的。
3. 继承时一种强耦合关系。
  所以,在《java编程思想》里有一个解决方法:问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承。

三、多态

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

还是先看一下代码:

public class People {
  public void fun1() {
    System.out.println("我是people的fun1");
    fun2();
  }
  public void fun2() {
    System.out.println("我是people的fun2");
  }
}
public class Man extends People {
  public void fun1(String a) {
    System.out.println("我是man的fun1");
    fun2();
  }
  public void fun2() {
    System.out.println("我是man的fun2");
  }
}
public class Demo {
  public static void main(String[] args) {
    People a = new Man();
    a.fun1();
  }
}

运行结果:

我是people的fun1
我是man的fun2

  从程序中我们可以发现,a.fun1()是先运行父类people中的fun1,再运行子类man中的fun2()。为什么会这样呢?因为在这个程序中子类man重载了父类people中的fun1()方法,重写了fun2()方法,重载以后,fun1(String a)和fun1()不是同一个方法,由于父类中没有该方法,向上转型以后就会丢失该方法,所以执行man的people类型应用是不能应用fun1(String a)方法的。而子类man重写了people中的fun2()方法,进行了覆盖,所以会调用man中的fun2()。
  所以,总结来讲:指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的,尽管是重载该方法。若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。
  对于面向对象而已,多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。
多态的实现条件:
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
   只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
  对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值