Java三大特征(封装/继承/多态)

89 阅读7分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Java三大特征(封装/继承/多态)

1、封装

封装的好处:

  1. 隐藏信息(权限),提供特定方法访问
  2. 方便加入控制语句
  3. 方便修改实现

封装的具体表现:

  • 属性用private修饰

  • 方法用public修饰

package JavaSE.JavaOOP.fz;
public class Book {
    /*
    	私有化属性
    */
    private String name;//书名
    private String author;//作者
    private double price;//定价
    private char ch ;//
    private Book(){}//私有化构造方法
    
    /*
    	public 方法 访问私有属性
    */
    
    //获取Book类的对象
    public static Book getBookObject(){
        if(book==null){
            book=new Book();
        }
        return book;
    }
    //修改定价
    public void setPrice(double p){
            price=p;
    }
    //获取定价
    public double getPrice(){
        return price;
    }
    //修改书名
    public void setName(String n){
        if(n.length()<20&&n.length()>0){
            name=n;
        }

    }
    //获取书名
    public String getName(){
        return name;
    }
    //修改作者
    public void setAuthor(String author){
        if(a.length()<15&&a.length()>0){
            this.author=author;
        }
    }
    //获取作者
    public String getAuthor(){
     return author;
    }
    //出版情况
    public void publish(){
        if(name!=null){
            System.out.println(name+"已出版");
        }
        else{
            System.out.println("未出版");
        }
    }
    //显示书本各种信息
    public void display(){
        System.out.println("书名:"+name+"\r\n作者:"+author+"\r\n定价:"+price);
        System.out.println(name+"已出版\r\n");
    }
}
package JavaSE.JavaOOP.fz;
//测试例
public class test1 {
    //单例模式:在程序中运行过程中,只创建一个对象
    public static void main(String[] args) {
        Book b = Book.getBookObject();//通过方法来实例化对象
        b.setAuthor("孙武");//设置作者
        b.setName("孙子兵法");//设置书名
        b.setPrice(36.8);//设置定价
        b.display();//显示信息
    }
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5wHSl54Z-1620610708502)(Java%E7%89%B9%E5%BE%81img/p8.jpg)]

this关键字

  1. this关键字代表自身类的对象
  • 使用this关键字引用成员变量

  • 使用this关键字引用成员方法

  1. 当方法中参数与与成员变量重名

    使用this区分

  2. 引用构造方法

注意:this关键字必须放在非静态方法里面

super() 从子类中调用父类的==构造==方法,this() 在同一类内调用其它方法

package JavaSE.JavaOOP.Packaging;
public class China {
    /*  private 修饰属性  */
    private String province;//省份
    private String national;//民族
    
    /*
        public 修饰方法
     */
    public China(){//无参构造方法
        System.out.println("China-->无参构造方法");
    }
	
    public China(int i){//有参构造方法
        System.out.println("China-->有参构造方法");
    }
	//设置省份
    public void setProvince(String province){
        this.province=province;
        //形参与变量重名时用this区分,this.变量名表示成员变量
    }
    //设置信息
    public void setInfo(String national){
        this.setProvince(province);//用this调用其他方法
        this.national=national;
    }
	//获取信息
    public void getInfo(){
        System.out.println(province);
        System.out.println(national);
    }
    
}
package JavaSE.JavaOOP.Packaging;

public class ChinaTest {
    public static void main(String[] args) {
        China c=new China();//创建对象
        c.setProvince("Shaanxi");//设置身份
        c.setInfo("汉");//设置民族
        c.getInfo();//获取信息
    }
}

运行结果:

在这里插入图片描述

2.继承

继承:从已有类派生出新类,新类拥有父类的所有非私有成员变量和成员方法.

Java中所有类都直接或间接继承了Object

何时使用继承?

动物:

猫,狗,猪,羊

书本:

纸质书

电子书

继承体现的关系:" is a "

继承是为了提升代码的复用性,节约成本

而不是为了继承而继承

当A类和B类符合,A是B的一种或B是A的一种,此时可以用继承

Java中只支持单继承,而不支持多继承,如图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Fk52XrV-1620610708512)(Java%E7%89%B9%E5%BE%81img/p9.png)]

package Test.extendsdemo;

//public class People extends Object
//Object类是Java中所有类的基类(超类)
//父类
public class People {
    //私有属性(子类无法访问)
    private String name;
    private int age;



    //公共方法    公共及构造方法都可继承
    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;
    }

    void sleep(){
        System.out.println("睡觉");
    }

    //构造器
    //无参构造
    public People() {
        System.out.println("父类无参构造");
    }
    //带参构造
    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
//子类
class Student extends People{
   /*
    重写/覆盖 override
    当父类方法不满足子类的需求,子类可重写父类方法

    注意:1静态方法/构造方法/成员变量  不能重写
        2重写父类方法,须结构一致(参数列表,方法名,返回值)
        3对于子类重写方法,访问权限修饰符:子类 >= 父类
    */
    private String xuehao;

    //构造器
    //无参
    public Student(){
        /*
        当创建一个子类对象时,会在子类构造方法中调用父类构造方法(先初始化父类成员)
        子类构造方法默认第一句调用super()为父类变量赋值初始化
         */
        System.out.println("子类无参构造");
    }
    //有参
    public Student(String name, int age, String xuehao) {
        super(name, age);
        /*
        显式调用super(),必须在子类构造方法第一句
        使用super()传参,调用指定的构造方法
        */
        this.xuehao = xuehao;
    }
     
    //子类重写父类方法  
    @Override
    //java 中的 注解标签 :覆盖,重写
    // 写了@Override,在编译过程中不符合规范时报错
    @Override
    public void sleep() {
        System.out.println("学生睡觉");
    }

    //子类特有方法
    public void learn(){
        System.out.println("学生学习");
    }
}

super:

在调用子类对象构造方法中

默认super()先调用 父类的无参构造方法 super()必须在第一句

也可显式调用

package Test.extendsdemo;
//测试例
public class PeopleTest {
    public static void main(String[] args) {
        People p=new People("Tom",21);
        Student s = new Student("Danny",21,"s1001");

        p.setName("Tony");//修改名字
        System.out.println(p.getName());//输出名字
        p.sleep();

        //父类方法
        s.setAge(31);//修改年龄
        System.out.println(s.getAge());//获取年龄
        s.sleep();

        s.setXuehao("s1010");//修改学号
        System.out.println(s.getXuehao());//获取学号
        s.learn();
    }
}

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R1QDmZDv-1620610708516)(Java%E7%89%B9%E5%BE%81img/p11.jpg)]

3.多态

同一事物在不同时刻表现不同状态

同一个接口,使用不同的实例而执行不同操作 (如)

多态存在的必要条件: 1.继承 2.方法重写(抽象类) 3.父类引用指向子类对象 三者缺一不可

使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。

我们在原来例子上稍加修改,上个例子中有继承,重写,现在我们在测试例中将父类引用指向子类对象即可

package Test.extendsdemo;

//public class People extends Object
//Object类是Java中所有类的基类(超类)
//父类
public class People {
    //私有属性(子类无法访问)
    private String name;
    private int age;

	String s="People";//非私有属性

    //公共方法    公共及构造方法都可继承
    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;
    }

    void sleep(){
        System.out.println("睡觉");
    }
    
    //父类静态方法
    public static void staticTest(){
        System.out.println("People静态方法");
    }

    //构造器
    //无参构造
    public People() {
        System.out.println("父类无参构造");
    }
    //带参构造
    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
//子类
class Student extends People{
   /*
    重写/覆盖 override
    当父类方法不满足子类的需求,子类可重写父类方法

    注意:1静态方法/构造方法/成员变量  不能重写
        2重写父类方法,须结构一致(参数列表,方法名,返回值)
        3对于子类重写方法,访问权限修饰符:子类 >= 父类
    */
    private String xuehao;

    String s="Student";
    //构造器
    //无参
    public Student(){
        /*
        当创建一个子类对象时,会在子类构造方法中调用父类构造方法(先初始化父类成员)
        子类构造方法默认第一句调用super()为父类变量赋值初始化
         */
        System.out.println("子类无参构造");
    }
    //有参
    public Student(String name, int age, String xuehao) {
        super(name, age);
        /*
        显式调用super(),必须在子类构造方法第一句
        使用super()传参,调用指定的构造方法
        */
        this.xuehao = xuehao;
    }
     
    //子类重写父类方法  
    @Override
    //java 中的 注解标签 :覆盖,重写
    // 写了@Override,在编译过程中不符合规范时报错
    @Override
    public void sleep() {
        System.out.println("学生睡觉");
    }
    
    //子类重写父类静态方法
    public static void staticTest(){
        System.out.println("Student静态方法");
    }

    //子类特有方法
    public void learn(){
        System.out.println("学生学习");
    }
}
package Test.extendsdemo;
//测试例
public class PeopleTest {
    public static void main(String[] args) {
       People p = new Student();//父类引用子类对象
        p.sleep();//公共方法
        /*    
        多态访问类中成员,
        编译期间调用父类方法,运行期间执行子类:编译看左边,运行看右边  
        对于静态方法和属性,编译与运行都看左边 
        */
        p.staticTest();//静态方法
        System.out.println(p.s);//属性
        
    }
}

我们将People 类的引用 p指向了Student对象,在使用p调用方法时,可以看到只能调用父类People的方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZdGvwhTI-1620610708519)(Java%E7%89%B9%E5%BE%81img/p12.jpg)]

运行看一下结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ed8c5mXy-1620610708522)(Java%E7%89%B9%E5%BE%81img/p14.jpg)]

可以看到构造方法和sleep方法都执行了子类的,子类构造方法中又默认先调用父类构造方法

静态方法和属性却访问父类

形如People p = new Student(); 称为向上转型

向上转型的父类引用只能调用父类方法,执行子类方法

想让父类也能调用子类方法,必须要向下转型

多态的实现方法

  • 重写

  • 抽象方法和抽象类

  • 接口

我们这里只用了一般的重写来实现多态,下一篇文章详细介绍抽象类与接口,并用它们实现多态