zoukankan      html  css  js  c++  java
  • 面向对象的三大特性

    三大特性

    封装

    一句话:属性私有化,get/set

    在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。

    封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

    要访问该类的代码和数据,必须通过严格的接口控制。

    封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。

    适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。

    优点

    1. 提高程序的安全性,保护数据。
    2. 隐藏信息,实现细节。
    3. 统一接口
    4. 减少耦合。

    实现封装

    1. 修改属性的可见性来限制对属性的访问(一般限制为private), 只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
    2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问
    public class Student {
        private int age;// 年龄
        private String name;// 名字
        
        // 提供一些public 的get、set方法。
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if (age > 100 || age < 0) {
                this.age = 3;
            } else {
                this.age = age;
            }
        }
    }
    
    

    采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。

    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            //student.name; // private私有化之后,外部类无法访问该属性。
            student.setName("小明");
            student.setAge(18); // 年龄在内部处理逻辑
            // student.setAge(999);  //处理不合理的年龄
            String name = student.getName();
            int age = student.getAge();
            System.out.println(name + age +"岁啦");
        }
    }
    

    以上实例中public方法是外部类访问该类成员变量的入口。

    通常情况下,这些方法被称为getter和setter方法。

    因此,任何要访问类中私有成员变量的类都要通过这些getter和setter方法。

    继承

    一句话:子类继承父类的特征和行为。

    extends 是"扩展"的意思,子类是父类的扩展。

    继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。

    继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

    特性

    • 子类拥有父类非 private 的属性、方法。
    • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
    • 子类可以用自己的方式实现父类的方法。(重写)
    • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 A 类继承 B 类,B 类继承 C 类,所以按照关系就是 C 类是 B 类的父类,B 类是 A 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
    • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。

    关键字

    继承可以使用 extends 和 implements 这两个关键字来实现继承,而且所有的类都是继承于 java.lang.Object,

    当一个类没有继承的两个关键字,则默认继承object祖先类(这个类在 java.lang 包中,所以不需要 import)。

    extends:在 Java 中,类的继承是单一继承,也就是说,一个子类只能拥有一个父类,所以 extends 只能继承一个类。

    implements:可以同时继承多个接口(接口跟接口之间采用逗号分隔),使java具有多继承的特性。

    public interface A {
        public void eat();
        public void sleep();
    }
     
    public interface B {
        public void show();
    }
     
    public class C implements A,B {
    }
    
    

    super:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。

    this:指向自己的引用。

    final :声明类可以把类定义为不能继承的,即最终类;或者用于修饰方法,该方法不能被子类重写:

    区别 前提 构造方法
    this 表示本身调用者这个对象 没有继承也可以使用 this()
    super 代表父类对象的引用 只能在继承条件才可以使用 super()

    注意点

    • super()调用父类的构造方法,必须在构造方法的第一个
    • this()调用自己的构造方法,必须在构造方法的第一个,所以this() super() 不能同时出现
    • super()只能出现在子类的方法或构造方法中!

    继承格式

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

    父类Person

    /**
     * 隐式继承Object类
     */
    public class Person {
        private String name;
        public void say() {
            System.out.println("说话说话");
        }
    }
    

    子类Student继承Person

    public class Student extends Person {
    
    }
    
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            student.say();
        }
    }
    

    子类继承了父类的公共方法和属性

    继承类型

    继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等

    img

    IDEA快捷键 ctrl + H 查看继承关系

    方法重写

    重写都是方法的重写,与属性无关

    image-20200510214544325

    重写:需要有继承关系,子类重写父类的非静态方法!

    1. 方法名必须相同
    2. 参数列表必须相同
    3. 修饰符可以扩大但不能缩小 public >protected>default>private
    4. 抛出的异常范围:可以被缩小但不能扩大;

    为什么需要重写?父类的功能,子类不一定需要,或者不一定满足。

    多态

    一句话:同一个方法可以根据发送对象的不同而采取多种不同的行为方式。

    使用手机扫描二维码支付时,二维码并不知道客户是通过何种方式进行支付,只有通过二维码后才能判断是走哪种支付方式执行对应流程。

    img

    多态可以实现动态编译:类型在执行过程中才可以确定:增强可扩展性~

    多态是同一个行为具有多个不同表现形式或形态的能力。

    多态就是同一个接口,使用不同的实例而执行不同操作。

    前提条件

    1. 继承
    2. 重写
    3. 父类引用指向子类

    特征

    • 对象能执行的方法和左边的类型有关,和右边的关系不大
    • 子类能调用的方法都是自己的或者继承父类的。
    • 父类型可以指向子类,但是不能调用子类独有的方法。
    • 父类想要执行子类的方法需要向下转型,高转低是强制转换!

    优点

    1. 减耦合
    2. 增强可以替换性
    3. 可扩展性
    4. 灵活性等

    关键词instanceof

    instanceof:测试它左边的对象是否是它右边的类的实例

    判断一个对象是什么类型,instanceof可以判断两个类之间是否存在父子关系

    image-20200512092823693

    public class Application {
        public static void main(String[] args) {
            // instanceof
            // 1.先判断左侧的引用类型与右边类是否有关系
            // 2.再判断左侧的实际类型与右边类是否有关系
    
            // 继承关系
            //      Object
            //      /   
            //  String  Person
            //          /   
            //     Student   Teacher
    
            // 公式 ClassA obj = new ClassB();
            // obj instanceof 任意类
            // 能够通过编译 取决于ClassA 与 任意类 有没有关系
            // true/false 取决于ClassB 与 任意类 有没有关系
    
    
            // 对象的引用类型是Student类
            Student obj1 = new Student();
            System.out.println("=======Student->Student==========");
            System.out.println(obj1 instanceof Student);
            System.out.println(obj1 instanceof Person);
            System.out.println(obj1 instanceof Object);
            // System.out.println(obj1 instanceof Teacher); // Student 和 Teacher 是兄弟关系,报错~
            // System.out.println(obj1 instanceof String); // Student 与 String无直接联系,报错!
    
    
            Person obj2 = new Student();
            System.out.println("=======Person->Student==========");
            System.out.println(obj2 instanceof Student);
            System.out.println(obj2 instanceof Person);
            System.out.println(obj2 instanceof Object);
            System.out.println(obj2 instanceof Teacher);
            // obj2 指向的是Student类,与Teacher无直接联系
            //System.out.println(obj2 instanceof String); // Person 与 String无直接联系,报错!
    
            Object obj3 = new Student();
            System.out.println("=======Object->Student==========");
            System.out.println(obj3 instanceof Student);
            System.out.println(obj3 instanceof Person);
            System.out.println(obj3 instanceof Object);
            System.out.println(obj3 instanceof Teacher);
            System.out.println(obj3 instanceof String);
    
            Person obj4 = new Person();
            System.out.println("=======Person->Person==========");
            //
            System.out.println(obj4 instanceof Student);
            System.out.println(obj4 instanceof Person);
            System.out.println(obj4 instanceof Object);
            System.out.println(obj4 instanceof Teacher);
            // System.out.println(obj4 instanceof String);
            // Person 与 String无直接联系,报错!
        }
    }
    
    

    类型转换

    基础类型转换

    • 低 ------>高 隐式转换
    • 高------->低 强制转换

    引用类型转换

    • 低(子类)----->高(父类)

    • 低转高:Person obj1 = new Student(); 即向上转换,不需要强制转换

    • 高转低 Student obj2 = (Student)obj1; 即向下转换,需要强制转换

    注意:之前学习继承的时候说,子类是父类的扩展,所以子类转换成父类时会丢失一些本身的方法或属性。

    父类型可以指向子类,但是不能调用子类独有的方法。因为子类独有的方法丢失了,无法调用。

    多态小结

    • 多态是方法的多态,属性没有多态

    • 父类和子类

      • 有联系。instanceof
      • 类型转换异常!ClassCastException!
      • 子类转换成父类,向上转型,丢失方法
      • 父类转换成子类,向下转型 (强制转换)
    • 存在条件

      • 继承关系
      • 方法需要重写
      • 父类引用指向子类对象!
    • 不能重写的方法

      • static 静态方法属于类,不属于实例
      • final常量修饰不能继承
      • private 方法私有

    OOP面向对象的编程思想就是抽象

    [代码区](# 多态代码)

    多态的表现

    多态代码

    第一种情况 对象的实际类型确定,指向的引用类型不确定(可以用父类引用类型指向子类对象)

    如下有Person类

    Person.java

    public class Person {
        public void say() {
            System.out.println("father---say");
        }
    }
    
    

    Student.java

    // 继承 Person 类
    public class Student extends Person {
    }
    
    

    有继承关系才可以指向

    Application.java

    /**
     * 测试多态的表现
     */
    public class Application {
        public static void main(String[] args) {
            // 一个对象的实际类型是确定的
            // new Student(); // 创建出一个学生
            // new Person();  // 创建出一个人
    
            // 可以指向的引用类型就不确定了
            Student s1 = new Student(); // new 一个学生 名字叫 学生
            Person s2 = new Student();// new 一个学生 名字叫 人(学生也是人,他继承了人)
            Object s3 = new Student();
            s2.say();
        }
    }
    
    

    运行结果

    father---say
    
    

    子类能调用的方法都是自己的或者继承父类的。如果子类中没有say方法,则调用继承于父类的say方法。

    如果在子类重写了父类的say方法,则调用本身的say方法。如下代码重写了父类的say方法:

    Student.java

    public class Student extends Person {
        @Override
        public void say() { // 重写父类say方法
            System.out.println("son ---- say");
        }
    }
    
    

    Application.java

    /**
     * 测试多态的表现
     */
    public class Application {
        public static void main(String[] args) {
            // 一个对象的实际类型是确定的
            // new Student(); // 创建出一个学生
            // new Person();  // 创建出一个人
    
            // 可以指向的引用类型就不确定了
            Student s1 = new Student(); // new 一个学生 由 学生
            Person s2 = new Student();// new 一个学生 由人接收(学生也是人,他继承了人)
            Object s3 = new Student();
            s1.say();// 学生 说
            s2.say();// 学生 说
            
        }
    }
    
    

    运行结果

    son ---- say
    son ---- say
    
    

    因为实例是确定的,s1,s2都是new 出来的Student()实例对象,方法的功能与实例的实现有关。

    如果在Student类中添加一个eat()方法

    public class Student extends Person {
        @Override
        public void say() {
            System.out.println("son ---- say");
        }
        
        public void eat() {
            System.out.println("son ---- eat");
        }
    }
    
    
    public class Application {
        public static void main(String[] args) {
    
            Student s1 = new Student();
            Person s2 = new Student();
    
            //对象能执行的方法和左边的类型有关,和右边的关系不大
            s1.say();// 学生 说
            s2.say();// 学生 说
    
            s1.eat(); // s1 左边是学生类,学生类里面有say方法。成功调用
            //s2.eat(); // s2 左边是人类,人类中没有eat方法,又不能继承,所以调用失败
        }
    }
    
    

    对象能执行的方法和左边的类型有关,涉及到类型转换,高-->低 会丢失精度。比如

    public class Test {
        public static void main(String[] args) {
            float a = 1.5f;
            long b = 99999999999999L;
            System.out.println((int)a); // 结果打印1 丢失了小数部分
            System.out.println((int)b); // 结果打印276447231  丢失数据溢出部分
        }
    }
    
    

    但在学习继承的时候知道,子类继承父类获取父类的非私有属性和方法,子类是父类的扩展。

    这里引用类型和基本类型的转换是存在区别的,基本类型高精度转型为低精度会丢失数据。而引用类型子类转型为父类会丢失方法或属性。

  • 相关阅读:
    HDU4529 郑厂长系列故事——N骑士问题 —— 状压DP
    POJ1185 炮兵阵地 —— 状压DP
    BZOJ1415 聪聪和可可 —— 期望 记忆化搜索
    TopCoder SRM420 Div1 RedIsGood —— 期望
    LightOJ
    LightOJ
    后缀数组小结
    URAL
    POJ3581 Sequence —— 后缀数组
    hdu 5269 ZYB loves Xor I
  • 原文地址:https://www.cnblogs.com/1101-/p/12882780.html
Copyright © 2011-2022 走看看