2.5 面向对象OOP(Object Oriented Programming)

目录

1. 初识面向对象

2. 方法的回顾与加深

3. 对象的创建分析

4. 面向对象的三大特性

5. 抽象类和接口

6. 内部类及OOP实战

1. 初识面向对象

  • 面向对象编程:Object Oriented Programming,OOP

  • 面向对象编程的本质就是:以类的形式组织代码,以对象的形式封装数据

  • 抽象

  • 三大特性:

    • 继承
    • 封装
    • 多态
  • 从认识论的角度考虑,是先有对象后有类。

    类,是抽象的;对象,是具体的。

  • 从代码运行的角度考虑,是先有类后有对象。类是对象的模板。

2. 方法的回顾与加深

  • 方法的定义

    • 修饰符

    • 返回类型

    • break(1.跳出switch;2.终止循环)和return(结束方法。返回结果。可以为空)的区别

    • 方法名(注意规范,见名知义)

    • 参数列表(参数类型,参数名)

    • 异常抛出

      public void readFile(String file) throws IOException{
              
          }
      
  • 方法的调用:递归

    • 静态方法

    • 非静态方法

      main方法

      package com.kuang.objectOrientedProgramming;
      
      public class StaticMethod 11{
          //1.静态方法static:直接Student.say调用
          //2.非静态方法:实例化new  对象类型 对象名 = 对象值
      
          public static void main(String[] args) {
              Student student = new Student();
              student.say();
              //形式参数和实际参数的类型要对应一致
              System.out.println(student.add(12,3));
              a();
          }
          // static:和类一起加载,直接使用
          public static void a(){
              b();
          }
          //无static:实例化后才能使用
          public static void b(){
              System.out.println("静态方法!");
          }
      }
      
      

      Student类

      package com.kuang.objectOrientedProgramming;
      
      public class Student {
          public void say(){
              //1.静态方法static:直接Student.say调用
              //2.非静态方法qZ
              //对象类型 对象名 = 对象值
              System.out.println("学生说话了");
          }
          //形式参数和实际参数的类型要对应一致
          public int add(int a, int b){
              return a+b;
          }
      }
      
      
    • 形参和实参(形参和实参类型要对应一致)

      precedent 先例

    • 值传递和引用传递

      package com.kuang.objectOrientedProgramming;
      //引用传递,本质还是值传递
      public class ValueRecedent {
          public static void main(String[] args) {
              int a = 1;
              System.out.println(a);
              ValueRecedent.change(a);
              System.out.println(a);
              //输出结果仍未1,说明是值传递。用Debug一步步跟进
      
              Person person = new Person();
              System.out.println(person.name);
              ValueRecedent.change(person);
              System.out.println(person.name);
              //输出结果由null->Shiki
          }
      
          public static void change(int a){
              a = 10;
          }
          //change方法重载,注意形参类型为Person类的person,因此实参不能是一个具体属性person.name
          public static void change(Person person){
              //person是一个对象,指向的是--->Person person = new Person(),这hi是一个具体的人,一定可以改变
              person.name = "Shiki" ;
          }
      }
      
      //一个类中可以有多个class,但是只能有一个public class
      class Person{
          String name;//不初始化,默认值为null
      
      }
      
      
    • this关键字(继承里面再讲)

3. 对象的创建方法

  • 类和对象的关系

    • 类是一种抽象的数据类型,它是对某一类事物的整体描述/定义,但是不能个代表某一个具体的事物
    • 对象是抽象概念的具体实例
  • 创建与初始化对象

    • 使用new关键字创建对象

      package com.kuang.objectOrientedProgramming.application;
      //一个项目之应该只有一个main方法,且越简单越好
      public class Application {
          public static void main(String[] args) {
              Student xiaoming = new Student();
              Student xiaohong = new Student();
              //类实例化后会返回自己的一个对象
              //Student对象就是Student 的一个具体实例
              xiaoming.name = "小明";
              xiaohong.name = "小红";
              xiaoming.age = 13;
              xiaohong.age = 23;
          }
      }
      
      package com.kuang.objectOrientedProgramming.application;
      
      public class Student {
          //一个类里面只有属性和方法
          //1. 属性
          String name;//null
          int age;//0
          // 2.方法
          public void  study(){
              //this表示当前类
              System.out.println(this.name+"在学习");
          }
      }
      
    • 使用new关键字的时候,除了分配内存空间外,还会给创建好的对象进行默认的初始化,以及对类中构造器的调用

      通过Project Structure 查看.class字节码文件

    • 类中的构造器也称构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点

      • 必须和类的名字相同
      • *必须没有返回类型,也没有void

      两个作用:

      • new的本质是在调用构造方法constructor
      • 初始化对象的值
      package com.kuang.objectOrientedProgramming.application;
      //一个项目之应该zhi有一个main方法
      public class Application {
          public static void main(String[] args) {
              Person person = new Person("Nothing");//new Person() ALT+回车
              System.out.println(person.name);
          }
      }
      /*
      Student xiaoming = new Student();
              Student xiaohong = new Student();
              //类实例化后会生产自己的一个对象
              //Student对象就是Student 的一个具体实例
              xiaoming.name = "小明";
              xiaohong.name = "小红";
              xiaoming.age = 13;
              xiaohong.age = 23;
       */
      
      package com.kuang.objectOrientedProgramming.application;
      //编译成功后去查看.class文件
      public class Person {
          //一个类即使什么都不写,它也会存在一个方法。
          //显示的定义构造器
          //类名相同且无参数。
          String name;
          //实例化初始值
          /*
          1. 使用new关键字,本质是在调用构造器(无参构造)
          2. (有参构造)一旦定义了有参构造,无参必须 显示定义,否则报错
           */
          public  Person(){
              this.name = "Shiki";
          }
          public  Person(String name){
              this.name = name;//this. 表示当前类
          //构造器快捷键constructor ALT + insert
          //有参构造和无参构造就是方法重载!
          }
      }
      
      

      关于快速创建构造方法的快捷键AlT +Insert

  • 构造器必须要掌握

  • 根据练习回想一下Java内存

    package com.kuang.objectOrientedProgramming.anmialBuild;
    
    public class Application {
        public static void main(String[] args) {
            Pet dog = new Pet();
            dog.name = "baozi";
            dog.age = 1 ;
            dog.shout();
            System.out.println(dog.age);
            System.out.println(dog.name);
    
        }
    }
    
    
    package com.kuang.objectOrientedProgramming.anmialBuild;
    
    public class Pet {
        public String name;
        public int age;
        public void shout(){
        System.out.println("wangwangwang~~~");
        }
    }
    
    

    结合这两张图

    属性的多种叫法:字段(field), 成员变量

4. **Java的三大特性:封装 继承 多态 **

  1. 封装

    封装,即隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别;将抽象得到的数据和行为(或功能)相结合,形成一个有机的整体,也就是将数据与操作数据的源代码进行有机的结合,形成“类”,其中数据和函数都是类的成员。

    程序设计目标:高内聚,低耦合。

    package com.kuang.objectOrientedProgramming.fengzhuang;
    
    public class App {
        public static void main(String[] args) {
            Student Shiki = new Student();
            //不能直接Shiki.age,因为属性私有。
            //用一些public的Get/set方法
            Shiki.setName("SK214");
            Shiki.setAge(21);
            Shiki.setSex('f');
            System.out.println(Shiki.getName());
            System.out.println(Shiki.getAge());
            System.out.println(Shiki.getSex());
        }
    }
    
    package com.kuang.objectOrientedProgramming.fengzhuang;
    
    public class Student {
        private String name;
        private int age;
        private char sex;
    
        //get获取,set设置
        /*
        封装的意义
        1.提高程序的安全性,保护数据
        2.隐藏代码的实现细节
        3.统一接口
        4.系统的可维护性增加了
    
         */
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if(this.age > 120 ||this.age <0 )
                System.out.println("Wrong Input!!!!");
    
            else
                 this.age = age;
    
        }
    
        public char getSex() {
            return sex;
        }
    
        public void setSex(char sex) {
            this.sex = sex;
        }
    }
    
  2. 继承

extends 拓展

类与类之间的关系:

继承关键字 :extends

称呼:父类/基类 -->子类/派生类

  • Object类:在Java中,所有的类都默认直接或者间接的继承Object类

  • super

    • super调用父类的构造方法,且必须在第一个
    • super必须只能出现在子类的方法或者构造方法中
    • super和this不能同时调用构造方法!
  • super与this的区别

    • 代表的对象不同:
      • this:本身调用者这个对象
      • super:代表父亲对象的应用
    • 前提:
      • this:没有继承也能使用
      • super:只有在继承条件下才能使用
    • 构造方法:
      • this:本类的构造
      • super:父类的构造
    package com.kuang.objectOrientedProgramming.extendss;
    
    public class App {
        public static void main(String[] args) {
            Students students = new Students();
            //students.sleep();
            //子类继承了父类的所有方法
            //System.out.println(students.money);
            //students.test("WeiNa");
           // students.test1();
        }
    }
    
    
    package com.kuang.objectOrientedProgramming.extendss;
    
    public class Person {
        /**
         * 4种修饰符
         * 1.public
         * 2.protected
         * 3.default  不写默认就是这个
         * 4.private
         */
    
        public Person(){
            System.out.println("Person无参构造器执行了");
        }
        int money = 100_000_000;//可以使用下划线来分割数字,便于认识
        protected String name = "HuangYe";
        public void sleep(){
            System.out.println("It's time to go to bed.");
        }
        public  void print(){
            System.out.println("Person");
        }
        //CTRL + H 查看继承树的快捷键。
        //在Java中,所有的类都默认直接或者间接的继承Object类
    
    
    }
    
    
    package com.kuang.objectOrientedProgramming.extendss;
    
    public class Students extends Person{
        public Students(){//无参构造器修饰符为public
            //new一个子类时,隐藏操作是先调用父类的无参构造
            super();//这一句调用父类无参构造可写可不写,但是一定要放在第一句,否则报错
            System.out.println("Students无参构造器执行了");
        }
        private String name = "orange";
        public void test(String name){
            System.out.println(name); //WeiNa
            System.out.println(this.name); //Orange
            System.out.println(super.name);  //HuangYe
        }
        public void test1(){
            print();  //Student
            this.print();  //Student
            super.print();  //Person
        }
        public void print(){
            System.out.println("Student");
        }
    
    }
    
    
  • 方法重写(不是方法重载,重载是同名但是参数不同)

Java是单继承,不是多继承!(可以多个儿子,但是不能多个父亲)

DP Dynamic Process 动态规划

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

  • 参数列表列表必须相同

  • 修饰符:范围可以扩大,public > protected >default > private

  • 抛出的异常:可以被缩小,但不能放大

    classNotFoundException -> Exception

重写子类的方法和父类的必须一致,方法体不同。

为什么需要重写:

  1. 父类的功能,对于子类来说过多或者过少

    Alt + Insert :override

package com.kuang.objectOrientedProgramming.overrideee;

public class App {
    public static void main(String[] args) {
        A a = new A();
        a.test();//输出A的test
        // B 是爹,父类的引用指向了子类
        //方法的调用值和左边,也就是定义的数据类型有关
        B b = new A();//输出B的test
        b.test();
    }
}

package com.kuang.objectOrientedProgramming.overrideee;
//重写都是方法的重写和属性无关
public class B {
    public static void test(){
        System.out.println("B的test");
    }
}


package com.kuang.objectOrientedProgramming.overrideee;


public class A extends B {
//    public void test(){
//        System.out.println("A的test");
//    }
    //Override 重写
    //@Override//注解,有注释的功能

    public static void test() {
        //super.test();
        System.out.println("A的test");
    }
}


带static

不带static

  1. 多态

多态:同一方法根据发送对象的不同而采取的多种不同的行为方式,多态让程序变得更灵活

一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多

qualifier 限定词,限定语

Student s1 = new Student();
引用类型 变量名 = new关键字 实际类型

多态的注意事项:

  • 多态是方法的多态,属性****没有多态
  • 父类和子类有联系。不相关的类型会异常,classCastException
  • 存在条件,继承关系,方法需要重写,父类指向子类对象。Father f1 = new Son()
    • static 方法,不能重写。属于类,他不属于实例
    • final 常量
    • private 方法
package com.kuang.objectOrientedProgramming.manyStage;

public class Application {
    public static void main(String[] args) {
        //一个对象的实际类型(指右边Student())是可以确定的
        //Student s1 = new Student();
        //引用类型 变量名 = new关键字 实际类型
        //对象的引用类型(左侧)就不确定了:例如下面第2,3条,父类的引用指向子类
        Student s1 = new Student();
        Person s2 = new Student();
        Object s3 = new Student();
        //对象能执行那些类型,主要看左边的引用类型,和右边的实际类型关系不大
        s2.run();//子类重写了父类的方法,执行子类的方法;子类没有重写,执行父类的方法
        //子类型可以调用自己的或者父亲的方法
        ((Student) s2).eat();  //父类型可以指向子类,但是不能调用子类独有的方法
        //(类型)高转低需要类型强制转换

    }
}

package com.kuang.objectOrientedProgramming.manyStage;

public class Person {
    public  void run(){
        System.out.println("run");
    }
}
package com.kuang.objectOrientedProgramming.manyStage;

public class Student extends Person{
    @Override
    public void run() {
        System.out.println("son");
    }
    public void eat(){
        System.out.println("eat");

    }
}

类型转换在基本数据类型那里就是:高容量转低容量

​ 在类和方法这里就是:父类转子类

instanceof (类型转换) 引用类型,判断一个对象是什么类型

先用instanceof 判断类型是否相似,然后再强制转换

false和编译不通过不一样

编译看左,运行看右

//左边的引用类型决定能否编译,右边的实际类型决定是true还是false,
        //编译看左,运行看右
        Object object = new Student();//外祖父引用孙子类
        System.out.println(object instanceof Student);//true
        System.out.println(object instanceof Person);//true
        System.out.println(object instanceof Object);//true
        System.out.println(object instanceof Teacher);//false
        System.out.println(object instanceof String);//false
        //----------------------------------------------------------
        Person person = new Student();//外祖父引用孙子类
        System.out.println(person instanceof Student);//true
        System.out.println(person instanceof Person);//true
        System.out.println(person instanceof Object);//true
        System.out.println(person instanceof Teacher);//false
        //System.out.println(person instanceof String);//报错,Person和String是Object下的同级关系

        //----------------------------------------------------------
        Student student = new Student();//外祖父引用孙子类
        System.out.println(student instanceof Student);//true
        System.out.println(student instanceof Person);//true
        System.out.println(student instanceof Object);//true
        //System.out.println(student instanceof Teacher);//报错
        //System.out.println(student instanceof String);//报错
        //----------------------------------------------------------

多态出现的条件

  1. 父类引用指向了子类的对象
  2. 把子类转换为父类,向上转型
  3. 把父类转换为子类,向下转型
  4. 方便方法的调用,减少new的代码

final 关键字后不能继承,断子绝孙

5. 抽象类以及接口

抽象类

  • abstract** 修饰符可以用来修饰方法,也可以修饰类。如果修饰方法,就是抽象方法。如果修饰类,就是抽象类。

  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定为抽象类。

  • 抽象类,不能使用new键字来创建对象,它是用来让子类继承的

  • 抽象方法,只用方法的声明,没有方法的实现,它是用来让子类实现的。

  • 子类继承抽象类,那么就必须要实现抽象类没有 实现的抽象方法,否则该孩子也声明为抽象类。

implement 是什么生效,贯彻执行;n. 工具器具用具

package com.kuang.objectOrientedProgramming.staticcc;

public abstract class Action {
    //约束,有人帮我们实现

    public Action(){//无参构造方法
        System.out.println("仿生人会梦见电子羊吗?");
    }

    public abstract void doSomething();// 抽象类中的抽象方法
    
    //abstract,抽象方法,只有方法名字,没有方法体来实现,子类继承必须要重写
    //1. 不能new这个抽象类,只能靠子类去实现它;约束!
    //2, 抽象类中可以写普通方法
    //思考:1.抽象类不能new,那么他能存在构造器吗?neng
    // 2.抽象类存在的意义  抽象出来~~~ 提高代码的开发效率
}

package com.kuang.objectOrientedProgramming.staticcc;

import com.kuang.objectOrientedProgramming.overrideee.A;

public class Abandon extends Action{//abstract 抽象类;extends 是单继承,但接口implement可以实现多继承

    @Override// 抽象方法的重写
    public void doSomething() {

    }
}

抽象类中可以有构造方法

class AbstractDemo01 {
    public static void main(String[] args) {
        B b = new B("哦");
        B b2 = new B();
    }
}

abstract class A {
    public A() {      
        System.out.println("抽象类A的构造方法");
    }
}

class B extends A {
    public B() { }

    public B(String name) {
        super(); //没有这句代码内部也会调用,默认隐式加上这句 
        System.out.println(name);
    }
}

接口

  • 区别与联系’
    • 普通类:只有具体细实现
    • 抽象类:具体实现和规范(抽象方法)都有
    • 接口:只有规范!没有实现的方法!约束和实现相分离
  • 关键字interface,接口的本质是契约
  • OO的精髓,是对抽象的抽象,最能体现这一点的就是接口
  • 作用:
    • 约束
    • 定义一些方法,让不同的人实现
    • 方法都是public abstract
    • 属性都是public static final
    • 接口中没有构造方法,不可以被实例化
    • implements可以实现多个接口
    • 总结博客
package com.kuang.objectOrientedProgramming.interfaceee;

public interface UserService { //接口关键字就是interface
    public abstract void run();
    //接口中的属性,常量
    public static final int AGE = 99;

    //接口默认的方法都是,public abstract 是灰色的,即默认是公共抽象,可以省去
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}


package com.kuang.objectOrientedProgramming.interfaceee;
//类可以实现implements接口,常见实现类的后缀就是--Impl,关键字implements
public class UserServiceImpl implements UserService,TimeService{
    @Override
    public void timer() {

    }

    @Override
    public void run() {

    }

    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }//逗号分隔,实现多继承

}


6. 内部类

匿名类,没有名字初始化类,不用将实例保存到变量中

new apple().eat()

package com.kuang.objectOrientedProgramming.OuterClass;

public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();
        //通过这个外部类outer按照顺序来实例化内部类
        Outer.Inner inner = outer.new Inner();
        inner.in();
    }
}

package com.kuang.objectOrientedProgramming.OuterClass;

public class Outer {
    private int id;
    public void out(){
        System.out.println("这是外部类的方法");
    }
    //类里面再写一个类。内部类
    public class Inner{
        public void in(){
            System.out.println("这是内部类方法");
        }
        public void getID(){
            System.out.println(id);//内部类可以get到外部类的私有属性
            //如果内部类Inner加上static修饰,getid就报错了。因为先实现static
        }

    }
}	
posted @ 2021-03-22 21:06  诸葛蛋蛋  阅读(104)  评论(0)    收藏  举报