【JavaSE】面向对象之三特性

访问控制修饰符

信息隐藏是 OOP 最重要的功能之一,也是使用访问修饰符的原因。在编写程序时,有些核心数据往往不希望被用户调用,需要控制这些数据的访问。
对类成员访问的限制是面向对象程序设计的一个基础,这有利于防止对象的误用。只允许通过一系列定义完善的方法来访问私有数据,就可以(通过执行范围检查)防止数据赋予不正当的值。
作用:

  • 防止对封装数据的未授权访问。
  • 有助于保证数据完整性。
  • 当类的私有实现细节必须改变时,可以限制发生在整个应用程序中的“连锁反应”。
访问范围 private default(默认) protected public
同一个类 可访问 可访问 可访问 可访问
同一包中的其他类 不可访问 可访问 可访问 可访问
不同包中的子类 不可访问 不可访问 可访问 可访问
不同包中的非子类 不可访问 不可访问 不可访问 可访问
public class Person {
    private String name;
    private int age;

    public Person(){}
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void display(){
        System.out.println("姓名:"+this.name+",年龄:"+this.age);
    }

    public static void main(String[] args) {
        Person p = new Person("wqc",20);
        p.display();
    }
}

一、封装

隐藏内部的实现细节,对外提供公共的访问方式。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
作用:

  1. 良好的封装能够减少耦合。
  2. 类内部的结构可以自由修改。
  3. 可以对成员变量进行更精确的控制。
  4. 隐藏信息,实现细节。

1.封装实现

私有化属性后,对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问。

public class Person{
    private String name;
    private int age;
​
    public int getAge(){
      return age;
    }
​
    public String getName(){
      return name;
    }
​
    public void setAge(int age){
      this.age = age;
    }
​
    public void setName(String name){
      this.name = name;
    }
}
public class Test {
    public static void main(String[] args) {
        Person p = new Person();
        p.setName("小王");
        p.setAge(20);
        System.out.println("姓名:"+p.getName());
        System.out.println("年龄:"+p.getAge());
    }
}

其中使用的this关键字是为了区别局部变量和成员变量

二、继承

继承实现了类层面的封装,提取了一个或多个类中的共性内容,定义在父类,子类哦通过继承父类去访问父类属性和方法。
所以,继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为

1.实现

class Person {
    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;
    }
}
class Student {
    private String name;
    private int age;
    private String schoolName;
    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;
    }
    public String getSchoolName()
    {
        return schoolName;
    }
    public void setSchoolName(String schoolName)
    {
        this.schoolName=schoolName;
    }
}

以上代码可以看出,两个类中有很多重复的内容,不符合Java语言的开发规范,这段代码不仅从代码上重复,而且从概念上讲学生一定是人,只是学生类描述的范围小,具备更多的属性和方法,这个时候想要消除结构定义上的重复,就要用到继承。

class Person {
    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;
    }
}
class Student extends Person{ 
  private String stuNo;
  public void setStuNo(String stuNo){
    this.stuNo = stuNo;
   }
  public String getStuNo(){
    return stuNo;
  }
}
public class Test2{
    public static void main(String[] args)
    {
        Student student=new Student();
        student.setName("花花");
        student.setAge(18);
        System.out.println("姓名:"+student.getName()+"  年龄:"+student.getAge());
    }
}

通过以上代码可以发现,当发生了类继承关系之后,子类可以直接继承父类的操作,可以实现代码的重用,子类最低也维持和父类相同的功能。

格式:

class 父类 {
}
 
class 子类 extends 父类 {
}

2.作用

1.提高代码的复用性
2.子类一旦继承父类,就有权访问父类中的内容
3.子类可以进行扩展,可以定义子类中独有的内容

3.注意

继承为单继承机制,一个子类只能继承一个父类,但可以多实现
一个父类可以被多个子类继承
单继承的优点:结构和操作简单
单继承缺点:不便于后期维护

4.重写

方法体的重新实现

4.1 与重载的区别

重载:
1.同一个类中的多个方法
2.方法名相同
3.参数列表不同|方法签名不同
重写:
1.不同的类
2.继承|实现
3.方法签名相同

4.2 不能重写的条件

1.被private修饰的成员方法不能被重写
2.被final修饰的成员方法不能被重写
3.被static修饰的成员方法不能被重写

4.3 检测是否重写

1.在行号的位置显示O↑
2.@Override注解是否报编译错误

4.4重写的条件

1.==:子类重写方法与父类中的方法签名完全相同
2.<=:返回值类型相同,基本数据类型完全相同,引用类型子类范围<=父类范围
3.>=:子类访问权限修饰符>=父类访问权限修饰符

三、多态

一种事物的多种表现形式

1.前提:

通过继承或者实现的方式

2.多态调用:

会调用子类中的重写方法,对子类新增不可见

3.调用成员方法:

编译看父类,运行找子类

4.调用成员变量:

编译运行看父类
多态引用调用时,对子类新增成员不可见

5.转型:

5.1向下转型

多态前提下,想要调用子类的新增内容需要向下转型
基本数据类型
小范围类型 变量 = (小范围类型)大范围类型
引用数据类型
子类类型 子类类对象 = (子类类型)父类类对象

5.2向上转型

父类引用指向子类对象
父类类型 引用变量 = new 子类类型();

6.注意

“java.lang.ClassCastException”类型转换异常

解决:instanceof:判断前面的引用指向的对象是否为后面类型的对象,或钱买你的引用是否指向后面类型的子类对象。
编译原则:只检查钱买你的引用与后面的类型是否在同一继承体系上,在则通过,不在则不通过

你可能感兴趣的:(【JavaSE】面向对象之三特性)