前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【趣学程序】java面向对象三大特征

【趣学程序】java面向对象三大特征

作者头像
趣学程序-shaofeer
发布2019-07-27 18:28:20
3800
发布2019-07-27 18:28:20
举报
文章被收录于专栏:upuptop的专栏

面向对象的三个特征

  1. 封装(Encapsulation);
  2. 继承(Inheritance);
  3. 多态(Polymorphism)。

封装

封装的两个含义:

  1. 把对象的状态和行为看成一个统一的整体,将二者存放在一个独立的模块中(类);
  2. "信息隐藏", 把不需要让外界知道的信息隐藏起来,尽可能隐藏对象功能实现细节,字段;

封装机制在程序中的体现是:把描述对象的状态用字段表示,描述对象的行为用方法表示, 把字段和方法定义在一个类中,并保证外界不能任意更改其内部的字段值,也不允许任意调动其内部的功能方法。

封装:通常将类中的成员变量私有化(private),通过对外提供方法(setXxx,getXxx),可对该变量(xxx)进行访问。 boolean 类型的变量没有getXX,只有 isXX;

代码语言:javascript
复制
public class Person{    private String name;    private int age;    private int sal;
    public String getName() {        return name;    }
    public void setName(String name) {        this.name = name;    }
    public int getAge() {        return age;    }
    public void setAge(int age) {        this.age = age;    }}

继承

特点:

  1. 提高了代码的复用性。
  2. 让类与类之间产生关系,有了这个继承关系才有了多态的特性。
  3. Java语言中只支持单继承(有别于C++语言)。 因为多继承容易带来安全隐患(父类多了, 功能相同的话,就会出现调用不确定性吗,覆写一个方法,到底覆写的谁的?)。 ps:接口可以实现多继承
  4. Java支持多层继承,object是每个类的超类,实现树形结构。

总结:继承是多态的前提。 对类而言,只支持单继承。接口可以实现多继承

格式:[修饰符]classSubClassextendsSuperClass

按照这种关系,我们把SuperClass类称为父类或基类,把SubClass称为子类或派生类或拓展类;

java.lang.Object是所有类的父类,Object要么是直接父类要么是间接父类。 定义个类,如果没有显示指定 extends继承某个类,那么默认继承 extendsObject

代码语言:javascript
复制
学生属于人的一种特殊情况,此时我把人的共性写在Person类里面,为了让学生拥有这些共性,然后我就让学生来拓展Person类。

public class Student extends Person {
    private String number;

    public String getNumber() {        return number;    }
    public void setNumber(String number) {        this.number = number;    }
    public void study() {        System.out.println("study");    }}

public class StudentDemo {    public static void main(String[] args) {        Person p = new Person();        p.setName("TOM");        p.setAge(20);        System.out.println("我是:" + p.getName() + ",今年" + p.getAge() + "岁。");

        Student s = new Student();        //Student中并没有显示的定义setName和setAge这两个方法,为什么可以使用呢?        //因为Student继承自Person,所以可以使用父类中的非私有属性和非私有方法        //在开发中,我们在优化代码的过程中,经常会将某几类共有的属性和方法向上提取,构造一个父类        s.setName("Lucy");        s.setAge(18);        s.setNumber("20180978");        System.out.println("我是:" + s.getName() + ",今年" + s.getAge() + "岁,我的学号是:" + s.getNumber());    }
}

总结:子类与父类的关系:

  1. 子类拓展父类(子类是父类的一种特殊情况)
  2. 主要是以父类为基础,然后添加属于自己的字段和方法。

注意:

  1. 父类的私有成员子类不能继承到;父类的构造方法不能被继承;
  2. Java只支持单继承,不支持多继承;//不然的话,比如show方法,继承了多个,不知道到底调用那一个。 一个类有且只有一个直接父类; 一个类没显示的继承其他的一个类的时候,默认的直接父类就是Object类;
  3. Student 的直接父类是Person,Object类也是Student类的父类,但是是间接父类; 4.一旦一个类显示的继承了其他的一个类的时候,此时默认的直接父类Object就会被取消;
  4. Java里一个类只能有一个直接父类;java.lang.Object是所有类的父类,Object要么是直接父类要么是间接父类。

super关键字

概述:

  1. 表示父类对象的默认引用
  2. 如果子类要调用父类被覆盖的实例方法,可用super作为调用者调用父类被覆盖的实例方法。

用途:

  1. 使用super调用父类方法
  2. 使用super调用父类的构造方法

调用构造方法

  1. 当前类中调用另一个重载构造方法使用 this(参数列表)
  2. 子类构造方法调用父类构造方法用 super(参数列表)

注意 子类调用父类的构造方法时: super必须放在第一句

子类构造会默认调用父类构造

初始化子类会优先初始化父类的数据.因为子类要继承父类的属性和方法,所以初始化子类时首先调用父类的构造方法。

代码语言:javascript
复制
修改person类:
public class Person {    private String name;    private int age;    private int sal;
    public Person(){        System.out.println("person 的无参构造");    }
    public String getName() {        return name;    }
    public void setName(String name) {        this.name = name;    }
    public int getAge() {        return age;    }
    public void setAge(int age) {        this.age = age;    }}

修改后的Student类:
public class Student extends Person {
    private String number;
    public Student() {        System.out.println("Student无参构造方法");    }
    public Student(String number) {        System.out.println("Student的有参构造");        this.number = number;    }
    public String getNumber() {        return number;    }
    public void setNumber(String number) {        this.number = number;    }
    public void study() {        System.out.println("study");    }}

测试类:
public class StudentDemo {    public static void main(String[] args) {        //    使用无参构造创建Student的对象        new Student();        //    使用有参构造创建Student的对象        new Student("100101");
        /*        打印结果:        person 的无参构造        Student无参构造方法        person 的无参构造        Student的有参构造
        */
    }
}

思考:如果父类没有无参构造这么办?

代码语言:javascript
复制
修改Person的构造方法,注意是修改,不是添加。只要类中有带参数的构造,无参构造方法将不会默认添加
    public Person(String name){        System.out.println("person 的无参构造");        this.name = name;    }
修改如上代码之后,点击保存。我们就会发现Student类中的两个构造方法报错。
修改Student的构造方法:
    public Student() {        super("TOM");        System.out.println("Student无参构造方法");    }
    public Student(String number) {        super("TOM");        System.out.println("Student的有参构造");        this.number = number;    }

为什么父类没有无参构造,代码编译不通过?

代码语言:javascript
复制
因为子类构造默认调用父类的无参构造方法,super(),可以省略:
   public Student() {        super();        System.out.println("Student无参构造方法");    }
    public Student(String number) {        super();        System.out.println("Student的有参构造");        this.number = number;    }

子类访问父类和方法覆写

  1. 子类不能直接访问父类的私有成员;
  2. 但是子类可以调用父类中的非私有方法来间接访问父类的私有成员。

例如:

代码语言:javascript
复制
Person类中有私有字段name,Student继承Personnew Sudent().name;        ×new Student().getName();    √
方法重写(Override)

产生原因

当父类中某个方法不适合于子类时,子类出现父类一模一样的方法.

特点:

  1. 方法声明必须相同,即方法的名称,方法的返回值,方法的参数类型,方法的参数个数都一致;
  2. 子类方法声明抛出的异常应比父类方法申明抛出的异常更小或相等;
  3. 子类方法的访问权限应比父类方法更大或相等;
代码语言:javascript
复制
   @Override    public void setAge(int age) {        System.out.println("Student类对setAge()方法自定义");        super.setAge(age);    }

如上所示:    我们可以在Student类中重写父类的setAge方法,并在内部实现自己的逻辑。    建议使用@Override注解进行标注重写的方法,因为如果不是重写的方法该注解会在编译器报错
    子类重写了方法,使用子类对象调用时,最终执行的就是子类重写的方法。    new Student().setAge(11);    执行结果:会打印【Student类对setAge()方法自定义】这句话

多态

概述:

多态,通俗说就是一个物体多种状态,比如水有气态,固态,液态。

表现形式:

  1. 编译时类型由声明该变量时使用的类型决定,运行时的类型由实际赋给变量的对象决定。
  2. 如果编译时类型和运行时类型不同,就出现多态。

例如:

代码语言:javascript
复制
    前提: Student extends Person
    在StudentDemo测试类中添加下列代码:
    Person ps = new Student();//这就是多态
在编译时期 ps 对象是Person,但是在运行时期    ps 对象 是Student
比如我们上面在Student类中重写了Person类中的setAge方法,那么你使用 ps 这个对象来调用setAge(111) 方法,他运行的就是Student类中重写的方法

实现多态的机制:

父类的引用变量可以指向子类的实例对象,而程序调用的方法在运行期才动态绑定, 就是引用变量所指向的真正实例对象的方法,也就是内存里正在运行的那个对象的方法, 而不是引用变量的类型中定义的方法。

多态的作用

把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。 只修改方法的实现,不必修改方法的声明。java中有面向接口编程也极大的展示了多态的特性。

继承/接口实现 是多态产生的前提条件

引用变量类型转换

代码语言:javascript
复制
向上转型(子类 →父类):由子类转为父类
    父类名称 父类对象 = 子类实例 ;      Person ps = new Student();

 向下转型(父类 → 子类):由父类转为子类  使用强制类型转换    子类名称 子类对象 = (子类名称)父类实例 ;    Person ps = new Student();    ps.setAge(123);    Student ss = (Student) ps;
向下转型注意:
    创建一个Worker类同时继承Person:

public class Worker extends Person{    private String job;
    public void setJob(String job) {        this.job = job;    }
    public String getJob() {
        return job;    }}

在StudentDemo的main方法中,添加:     Person pw = new Worker();     Student sss = (Student) pw;
将一个Worker强转为Student。    会报异常:java.lang.ClassCastException:Worker cannot be cast to Student
如何判断pw是否是Student类型呢?使用instanceof关键字    Person pw = new Worker();
    if (pw instanceof Student) {        Student sss = (Student) pw;    }

对象名   instanceof  类
判断指定的变量名此时引用的真正类型是不是当前给出的类或子类;
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 趣学程序 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 封装
    • 封装的两个含义:
    • 继承
      • super关键字
        • 子类构造会默认调用父类构造
          • 子类访问父类和方法覆写
            • 方法重写(Override)
        • 多态
        • 引用变量类型转换
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档