2021_03_02_面向对象

面向对象编程

什么是面向对象

  • 面向过程:

    • 步骤清晰简单,第一步。。。第二步。。。
    • 面对过程适合处理一些较为简单的问题
  • 面向对象:

    • 物以类聚。解决问题前先思考解决问题需要的分类。然后对分类进行单独思考。最后,对某个分类下的细节进行面向过程的思考
    • 面向对象容易将复杂问题拆分。也因此适合多人协作完成问题的处理。
    • 面向对象在宏观上能系统得分析问题,而在微观操作层面依然需要面向过程的思路去处理。
  • 什么是面向对象编程

    • OOP, Object-Oriented Programming

    • 面向对象编程的本质:

      以类的方式组织代码,以对象组织(封装)数据。

    • 抽象

    • 三大特征:

      • 封装
      • 继承
      • 多态
    • 类是抽象的。对象,是从类演化而来的实例。


方法的回顾和加深

  • 方法的定义:

    • 修饰符
    • 返回类型
    • break和return的区别
      • break:跳出循环,跳出switch
      • return:方法结束,同时返回结果。返回结果要和返回类型对应。
    • 方法名:命名规范,见名知意
    • 参数列表:(参数类型, 参数名)
    • 异常抛出:之后详解
  • 方法的调用:

    • 静态方法
    • 非静态方法
    // 学生类
    public class Student {
        public static void main(String[] args) {
    
        }
    
        //学习,静态方法
        public static void study(){
            System.out.println("学生学习了");
        }
    
        //说话,非静态方法
        public void say(){
            System.out.println("学生说话了");
        }
    
    }
    
    import OOP.Student;
    
    public class Demo01 {
        public static void main(String[] args) {
    
            //调用静态方法学习
            Student.study();
    
            //调用非静态方法说话
            Student student1 = new Student(); // 先实例话
            student1.say(); // 在实例中使用说话方法
        }
    }
    
    //学生学习了
    //学生说话了
    
    • 形参和实参
    • 值传递个引用传传递
    • this关键字:表示当前类 (类似python的self)

对象的创建分析

  • 创建与初始化对象

    • 使用new关键词穿件对象
    • 使用new关键词创建的时候,除了分配内存空间之外,还会给创建好的对象 进行默认的初始化
    //学生类
    public class Student {
    
        //属性
        String name;
        int age;
    
        //方法
        public void study(){
            System.out.println(this.name + " is studying.");
        }
    }
    
    /执行文件
    public class Application {
    
        //每个项目只需要一个主程式,一般包含在执行文件中
        public static void main(String[] args) {
    
            //创建一个实例student1
            Student student1 = new Student();
    
            //设置student1的name
            student1.name = "XJY";
    
            //设置student2的age
            student1.age = 18;
    
            //使用student1的study方法
            student1.study();
        }
    }
    
    //XJY is studying.
    
    • 类中的构造器也称为构造方法,在进行创建对象的时候必须要调用的。构造器有以下两个特点:
      • 必须和类的名字相同
      • 必须是没有返回类型,也不用写关键字void
public class Person {
    
    String name;
    
    //构造器 如果不定义则默认生成
    //快捷键 alt+insert
    public Person(String name){
        //初始化name
        this.name = name;
    }
}
public class Application2 {
    public static void main(String[] args) {
        Person p1 = new Person("XJY");
        System.out.println(p1.name);
    }
}

//XJY

面向对象三大特征

  • 封装

    • 该露的露,该藏得藏:

      程序设计讲究“高内聚,低耦合”

      高内聚就是类的内部数据操作细节自己完成,不允许外部干涉

      低耦合指的是仅仅暴露少量接口供外部使用

    • 封装(数据的隐藏)

      通常,应当禁止直接访问一个对象中数据的实际表示,而应该通过接口来访问,这样就能做到信息隐藏。

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

public class Student {

    //private 私有属性
    private String name;
    private int idNumber;
    private boolean sex; //male - true; female - false

    public Student() {
        this.name = "XXX";
        this.idNumber = 0;
        this.sex = true;
    }

    public Student(String name, int idNumber, boolean sex) {
        this.name = name;
        this.idNumber = idNumber;
        this.sex = sex;
    }

    //提供一些可以访问私有属性的方法
    //提供一些public的get、set方法

    //get
    public String getName(){
        return this.name;
    }

    public int getIdNumber(){
        return this.idNumber;
    }

    public String getSex() {
        if (this.sex) {
            return "Male";
        }else {
            return "Female";
        }
    }

    //set
    public void setName(String name){
        this.name = name;
    }

    public void setIdNumber(int idNumber) {
        this.idNumber = idNumber;
    }

    public void setSex(String sex) {
        if (sex.equals("Male")) {
            this.sex = true;
        } else if (sex.equals("Female")) {
            this.sex = false;
        }else {
            System.out.println("性别录入失败");
        }
    }

    //alt+inset 快捷键可以快速创建get set方法
}
public class Application {
    public static void main(String[] args) {
        boolean flag = true;
        Student student1 = new Student();

        student1.setName("XJY");
        System.out.println("Name is " + student1.getName());

        student1.setIdNumber(30);
        System.out.println("ID is " + student1.getIdNumber());

        student1.setSex("Female");
        System.out.println("Sex is " + student1.getSex());
    }
}

//Name is XJY
//ID is 30
//Sex is Female
  • 继承

    • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。

    • extends的意思是扩展。子类是父类的扩展。

    • JAVA中类只有单继承,没有多继承。

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

    • 继承关系的两个类,一个是子类,一个是父类,子类继承父类用关键字extends来表示

    • 子类和父类之间,从意义上讲应该具有“is a”的关系

    • object类,所有类都是object类的子类

    • super,调用父类构造器时使用的关键字

    //人类
    public class Person {
    
        //私用属性无法继承
        private String name;
        int age;
    
        public Person() {
            this.name = "XXX";
            this.age = 10;
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void say(){
            System.out.println("人说话");
        }
    }
    
    //学生类 is 人类
    public class Student extends Person{
    
        public Student() {
            super();
        }
    
        public Student(String name, int age) {
            
            //使用super可以调用父类的构造器方法 必须在子类构造器的第一行
            super(name, age);
        }
    }
    
    public class Application {
    
        public static void main(String[] args) {
            Student student1 = new Student("XJY", 10);
            student1.say();
            System.out.println(student1.getName());
        }
    
    }
    
    //人说话
    //XJY
    
    • 方法重写:

      需要有继承关系。子类重写父类的方法。

      public class A {
      
          public void test(){
              System.out.println("Test A");
          }
      
          public void test2(){
              System.out.println("Test2 A");
          }
      }
      
      // 重写方法演示
      public class B extends A{
      
          //方法重写
          @Override
          public void test(){
              System.out.println("Test B");
          }
      
          //alt+insert 可以直接调出override method的快捷功能
      
          @Override
          public void test2() {
              System.out.println("Test2 B");
          }
      }
      
      public class Application {
      
          public static void main(String[] args) {
      
              B object1 = new B();
              //父类的引用可以指向子类 这里B为A的子类
              A object2 = new B();
              A object3 = new A();
      
              object1.test();
              object2.test();
              object3.test();
              object1.test2();
              object2.test2();
              object3.test2();
      
          }
      }
      
      //Test B
      //Test B
      //Test A
      //Test2 B
      //Test2 B
      //Test2 A
      

      注意:

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

    • 同一个方法可以根据发送的对象不同而采用不同的行为方式
    • 一个对象的实际类型是确定的,但是可以指向对象的引用类型有很多
    • 多态的存在条件:
      • 有继承关系
      • 子类重写父类的方法
      • 父类引用指向子类对象
    • 注意:多态是方法的多态,属性没有多态性。
    public class Person {
    
        public void run(){
            System.out.println("RUN");
        }
    }
    
    
    public class Student extends Person {
        @Override
        public void run() {
            System.out.println("Student Run");
        }
    
        public void goToSchool() {
            System.out.println("Go to School.");
        }
    }
    
    
    public class Application {
        public static void main(String[] args) {
    
            Student s1 = new Student();
            Person s2 = new Student();
    
            /*
            一个对象的实际类型是确定的.
            比如这里的s1以及s2确定属于Student类
            但是应用类型可以不一样。这边s2引用的就是父类Person类
            注意,只有父类才能被子类型引用,反过来是不行的
             */
    
            //子类重写父类,则都执行父类方法
            s1.run();
            s2.run();
    
            //子类独有的方法只有引用了Student的实例才能使用
            s1.goToSchool();
            //通过强制转换类型,可以让s2也能调用子类的方法
            ((Student) s2).goToSchool();
        }
    }
    
    //Student Run
    //Student Run
    //Go to School.
    //Go to School.
    
    • 关键字 instanceof : 判断一个对象是什么类型
    public class Person {
    }
    
    public class Student extends Person{
    }
    
    public class Teacher extends Person{
    }
    

    以上为三个类,Student和Teacher均为Person的子类,那么执行以下命令会发现

    public class Application {
        public static void main(String[] args) {
            Object student1 = new Student();
            System.out.println(student1 instanceof Student);
            System.out.println(student1 instanceof Person);
            System.out.println(student1 instanceof Object);
            System.out.println(student1 instanceof Teacher);
            System.out.println(student1 instanceof String);
            System.out.println("============");
    
            Person student2 = new Student();
            System.out.println(student2 instanceof Student);
            System.out.println(student2 instanceof Person);
            System.out.println(student2 instanceof Object);
            System.out.println(student2 instanceof Teacher);
            System.out.println("============");
    
            Student student3 = new Student();
            System.out.println(student3 instanceof Student);
            System.out.println(student3 instanceof Person);
            System.out.println(student3 instanceof Object);
            System.out.println("============");
        }
    }
    
    //true
    //true
    //true
    //false
    //false
    //============
    //true
    //true
    //true
    //false
    //============
    //true
    //true
    //true
    //============
    
  • static修饰的方法个变量和类一起加载。

    public class Student {
    
        //第二个执行
        {
            System.out.println("匿名代码块");
        }
    
        //第一个执行 但是只执行一次
        static {
            System.out.println("静态代码块");
        }
    
        //第三个执行
        public Student() {
            System.out.println("构造器");
        }
    
        public static void main(String[] args) {
            Student student1 = new Student();
            System.out.println("====");
            Student student2 = new Student();
        }
    }
    
    //静态代码块
    //匿名代码块
    //构造器
    //====
    //匿名代码块
    //构造器
    

抽象类和接口

  • 抽象类

    //抽象类
    public abstract class Action {
    
        //抽象方法 约束 有人会帮我们实现
        //只有方法名字 没有方法的实现
        public abstract void doSomething();
    }
    
    //继承了抽象类的类 必须实现抽象类中所有的方法
    //除非该类也是抽象类
    public class A extends Action{
    
        @Override
        public void doSomething() {
    
        }
    }
    
  • 抽象类的特点:

    • 不能实例化,只能子类继承
    • 只有抽象类中才能定义抽象方法,但是抽象类中可以写普通方法
    • 抽象类只是一种约束条件
    • 抽象类相当于创建类的一个模板,能够提高开发效率
  • 接口

    • 普通类:只有具体实现; 抽象类:具体实现和规范都有 接口:只有规范
    • 接口就是规范。定义的是一组规则。“如果你是。。则你必须能。。。”的思想。
    • 接口的本质是契约,就像法律。制定好之后所有程序遵守。
    • OO的精髓是对对象的抽象,最能体现这一点就是接口。
    • 声明接口的关键字是interface
    • 接口可以实现多继承

    第一个接口,

    //interface 接口 都需要一个实现类UserServiceIMPL (一般实现类以IMPL结尾)
    public interface UserService {
    
        //常量 public static final
        int IP = 1000876;
        
        //接口中的所有定义都是抽象的公开的 public abstract
        void user();
    }
    

    第二接口,

    public interface TimeService {
        void timer();
    }
    
    //类可以实现接口 使用关键词implements
    //可以连接多个接口
    //通过接口可以实现多继承
    public class UserServiceIMPL implements UserService, TimeService{
    
        @Override
        public void timer() {
    
        }
    
        @Override
        public void user() {
    
        }
    }
    

内部类

  • 内部类

    • 内部类就是在一个类的内部再定义一个类

    • 成员内部类

      public class Outer {
      
          //外部类定义部分
          private int id = 10;
          public void out(){
              System.out.println("From Outer");
          }
      
          //定义内部类Inner
          public class Inner{
      
              public void in(){
                  System.out.println("From Inner");
              }
      
              //获得外部类的私有属性
              public int getID(){
                  return id;
              }
      
              //获得外部类的方法
              public void inOuter() {
                  out();
              }
          }
      }
      
      public class Application {
      
          public static void main(String[] args) {
              Outer outer1 = new Outer();
              //通过实例化的outer1来实例化一个inner1
              Outer.Inner inner1 = outer1.new Inner();
      
              //访问自己的方法
              inner1.in();
              //访问获得来的外部类的方法
              inner1.inOuter();
              //方位获得来的外部类的私有属性
              System.out.println(inner1.getID());
      
          }
      }
      
      //From Inner
      //From Outer
      //10
      
    • 静态内部类

      public class Outer {
      
          //外部类定义部分
          private int id = 10;
          public static void out(){
              System.out.println("From Outer");
          }
      
          //定义静态内部类Inner 和类一起加载
          public static class Inner{
      
              //静态方法
              public static void in(){
                  System.out.println("From Inner");
              }
      
              //无法获得外部类的私有属性 因为和类一起加载时还没有定义id
      
              //无法获得非静态的外部类的方法
              //但可以获得静态的外部类
              public void inOut(){
                  out();
              }
          }
      }
      
      public class Application {
      
          public static void main(String[] args) {
      
              //直接调用静态类的静态方法 无需实例化
              Outer.Inner.in();
      
              //可以直接使用new关键字来实例化一个inner1
              Outer.Inner inner1 = new Outer.Inner();
              //调用传递过外部静态方法的内部方法
              inner1.inOut();
      
          }
      }
      
      //From Inner
      //From Outer
      
    • 局部内部类

      public class Outer {
      
          public void method(){
              //在方法中可以定义局部内部类
              class Inner{
                  public void in(){
                      System.out.println("From Inner");
                  }
              }
      
          }
      }
      
      
    • 匿名内部类

      public class Test {
          public static void main(String[] args) {
      
              //实例不保存在变量中,没有初始化类直接调用其中的方法
              new Apple().showColor();
      
              //省去实现接口的类的名字,直接通过接口实例化一个service1
              UserService service1 = new UserService(){
                  @Override
                  public void hello() {
                      System.out.println("Hello");
                  }
              };
      
              service1.hello();
          }
      }
      
      class Apple {
      
          public void showColor(){
              System.out.println("Red");
          }
      }
      
      interface UserService {
          void hello();
      }
      
      //Red
      //Hello
      
    • 并行类

      public class ClassA {
      }
      
      
      //一个java文件可以有多个类或接口 但只能有一个public的类
      class ClassB{
      }
      
      interface UserService{
      }
      
posted @ 2021-03-09 15:17  cutomorrow  阅读(77)  评论(0)    收藏  举报