JAVA面向对象

初识面向对象

思想

  • 物以类聚,分类的思维模式,思考问题首先会解决问题需要那些分类,然后对这些分类进行单独思考,最后,才对某个分类下的细节进行面向过程的思考
  • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题
  • 对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
  • 面向对象的本质就是:以类的方式组织代码,以对象的形式组织(封装)数据*
  • 抽象
  • 特性:封装、继承、多态
  • 从认识的角度思考是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象
  • 从代码运行角度考虑是先有类后有对象,类是对象的模板。
public class OopDemo1 {
    public static void main(String[] args) {
        //创建Cat对象
        //cat1是对象名(对象引用)
        //new Cat() 创建的对象空间(数据),才是真正的对象
        Cat cat1 = new Cat();
        cat1.age = 5;
        System.out.println(cat1.age);
        cat1.say();
    }
    //对象的属性默认值,遵守数组规则
    //默认值:int 0,short  0, byte  0,  long  0,  float  0.0,  double  0.0,  char \u0000,  boolean   false,String  null;
    //当不进行初始化赋值时,都是默认初始化值
}
class Cat{
    String name;//属性
    int age;//属性
    String color;//属性
    public void  say(){//行为
        System.out.println("叫了一声");
    }
}

对象的创建

  • 类是一种抽像的数据类型,他是对某一类事物整体描述/定义,但是并不能代表某一个事物的具体的事物
  • 成员变量 = 属性 = field(字段)
  • 属性是类的一个组成部分,一般是基本数据类型,也是引用类型(对象,数组)。比如定义一个猫类的int age 就是属性
  1. 先声明在创建
Cat cat;//声明对象cat
cat = new Cat();//创建
  1. 直接创建
Cat cat = new Cat();

在这里插入图片描述

  • 对象是抽象概念的具体的实例
  1. 使用new关键字创建对象
  2. 使用new关键字创建对象的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构建器的调用
  3. 类中的构造器也成为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
  • 必须和类的名字相同
  • 必须没有返回类型,也不能写void
  1. 构造器必须要掌握

封装

  • 把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法),才能对数据进行操作

  • 封装的好处和理解

    • 隐藏实现细节
    • 可以对数据进行验证,保证安全合理
  • 该漏的漏,该藏的藏

    • 程序设计要追求”高内聚,低耦合“。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用
  • 封装(数据的隐藏)

    • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口有来访问,这称为信息隐藏
  • 属性私有,get(获取属性的值)/set(判断属性并赋值)

  • /*1.提高程序的安全性,保护数据
    2.隐藏代码的实现细节
    3.统一接口
    4.增加了系统的可维护性
    */
    

继承

  • 继承的本质是对某一批类的抽象,从而事项对现实世界更好的建模
  • 继承可以解决代码复用,让我们的编程更加靠近人类思维,当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可
  • extends的意思是“扩展”。子类是父类的拓展,继承后子类自动拥有父类定义的属性
  • 继承所带来的便利:
    • 代码的复用性提高了
    • 代码的拓展性和维护性提高了

细节

  1. 子类继承了所有的属性和方法,但是私有属性不能再子类直接访问,要通过公共的方法去访问
  2. 子类必须调用父类的构造器,完成父类的初始化
  3. 当创建对象时,不管使用子类的那个构造器,则必须再子类的构造器中用super去指定使用父类的那个构造器完成对付类的初始化工作,否则,编译不会通过,如果父类中没有写构造器,则默认调用无参构造器,如果父类中写了有参构造器,则必须在子类的构造器中写明调用的是父类的那个构造器
  4. 如果希望指定去调用父类的某个构造器,则显示的调用一下:super(参数列表)
  5. super在使用时,需要放在构造器第一行
  6. super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
  7. java所有类都是Object类的子类
  8. 父类构造器的调用不限于直接父类!将一直网上追溯知道Object类(顶级父类)
  9. 子类最多只能继承一个父类(直接继承),即Java中式但继承机制
  10. 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系
  • Java中只有单继承没有多继承
    • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖,组合,聚合等
    • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示

在这里插入图片描述

public class Test {

    public static void main(String[] args) {
        Son son = new Son();//内存的布局
        //这时应该注意,要按照查找关系来返回信息
        //1.首先看子类是否有该属性
        //2.如果子类有这个属性,并且可以访问,则返回信息
        //3.如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息)
        //4.如果父类没有按照3.的规则,继续招商及父类,知道Object
        System.out.println(son.name);
        System.out.println(son.age);
        System.out.println(son.hobby);

    }
}
class Son extends Father{
    String name = "大头儿子";

}
class Father extends GrandePa{
    String name = "大头爸爸";
    int age = 53;
}
class GrandePa {
    String name = "大头爷爷";
    String hobby = "旅游";
}

  • object类
public class Person {
    public Person() {
        System.out.println("Person无参执行了");
    }

    protected String name = "shenghao";

    //public    公共的  优先级最高
    //protected  受保护的
    //default   默认的
    //private   私有的   优先级最低
    private int money = 1000;

    public void say() {
        System.out.println("shuojuhua");
    }
    public void print(){
        System.out.println("Person");
    }
//私有的方法无法被继承
    public int getMoney() {
        return this.money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}

//学生 :  派生类 子类
//子类继承了父类,就会拥有父类的全部方法
public class Student extends Person{
    public Student() {
        //隐藏代码,调用了父类的无参构造
        super();//调用父类的构造器,必须压迫在子类构造器的第一行
        System.out.println("Student无参执行了");
    }

    private  String name = "sheng";

    public void  print(){
        System.out.println("Student");
    }

    public void test1(){
        print();
        this.print();
        super.print();
    }

    public  void test(String name){
        System.out.println(name);//盛浩
        System.out.println(this.name);//sheng
        System.out.println(super.name);//shenghao
    }
public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        Person p1 = new Person();
        student.say();
        student.setMoney(100);
        System.out.println(student.getMoney());
        student.test("盛浩");
        student.test1();
    }
package Test2;
/*
编写Computer类,包含CPU,内存,硬盘等属性,getDetails方法用于返回Computer的详细信息
编写PC子类,继承Computer类,添加特有属性[品牌brand]
编写NotePad子类,继承Computer类,添加特有属性[演示color]
编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,以及从Computer类继承的属性赋值,并使用方法打印输出信息
 */
public class Computer {
    public String cpu;//芯片
    public int memory;//内存

    public String hard;
    public Computer(String cpu,int memory,String hard){
        this.hard = hard;
        this.memory = memory;
        this.cpu = cpu;
    }


    public  String getDetails(){
        return "cpu:"+cpu+" memory:"+memory+" hard:"+hard;
    }
}
class PC extends Computer{
    //编写PC子类,继承Computer类,添加特有属性[品牌brand]
    public String brand;//品牌
    public PC(String brand,String cpu,int memory,String hard){
        super(cpu,memory,hard);
    }

    public  void showInfo(){
        System.out.println("品牌"+brand+getDetails());
    }

}
class NotePad extends Computer{
    //编写NotePad子类,继承Computer类,添加特有属性[演示color]
    public String color;
    public NotePad(String color,String cpu,int memory,String hard){
        super(cpu,memory,hard);

    }
    public  void showInfo(){
        /*
        找getDetails的方法时(getDetails()和this.getDetails())的顺序是:
        首先找本类,如果有,则调用
        再找父类,如果有,则调用
        父类找不到,继续往上找,一直到Object类
        提示:在查找方法的过程中,如果找不到,则提示方法不存在
            在查找方法的过程中,如果找到了,但是不能访问,则报错
            this.方法名:从本类开始找
            super.方法名:从父类开始找
         */

        System.out.println(getDetails()+"颜色:"+color);
    }

}
    //编写Test类,在main方法中创建PC和NotePad对象,分别给对象中特有的属性赋值,
    // 以及从Computer类继承的属性赋值,并使用方法打印输出信息
public class ComTest {
        public static void main(String[] args) {
            PC pc = new PC("华为","rtx4090",1024,"C盘");

            NotePad notePad = new NotePad("white","rtx4090t",1024,"d盘");
            pc.showInfo();
           notePad.showInfo();
        }
}

  • super

    • 调用父类的构造器,必须压迫在子类构造器的第一行

    • 访问父类的属性,但不能访问父类的private属性 super.属性名

    • 访问父类的方法,不能访问父类的private方法 super.方法名(参数列表)

    • 调用父类的构造器的好处,(分工明确,父类属性由父类初始化,子类属性有子类初始化)

    • 当子类中有父类的成员(属性和变量)崇明是,为了访问父类的成员,必须通过super。如果没有重名,使用super,this,直接访问是一样的效果

    • super的访问不限于直接父类,如果父类的父类和本类也有同名的成员,也可以使用

    • super去访问爷爷类的成员,如果多个基类(上级类)中都有同名的成员,使用super访问遵循就近原则

    • 访问父类的构造器

      • super(参数列表);只能放在构造器的第一句!
    • super注意点:
      1.super调用父类的构造方法,必须在构造方法的第一行
      2.super必须只能出现在子类的方法或者构造方法中
      3.superthis不能同时调用构造方法
      
      
      vs this:
          代表的对象不同:
              this:本身调用者这个对象
              super:代表父类对象的应用
          前提
              this:没有继承也可以使用
              super :只能在继承条件下才可以使用
          构造方法:
              this();本类的构造
              super();父类的构造
      

      在这里插入图片描述

  • 方法重写

    • 基本介绍:
      • 简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名称,返回类型,参数一样,那么我们就说子类的这个方法覆盖了父类的那个方法
    • 方法重写也叫方法覆盖,需要满足下面的条件
      • 子类的方法的形参列表,方法名称要和父类方法的参数,方法名称完全一样。
      • 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
      • 子类方法不能缩小父类方法的访问权限 public >protected>默认>private,父类如果是public,子类就不能是peotected
public class A extends B{
    //Override重写

    @Override//注解:有功能的注释!
    public void test() {
        System.out.println("A=>test()");
    }
}
//重写都是方法的重写,和属性无关

public class B {
    public void test() {
        System.out.println("B=>test()");
    }
}

public class Application1 {
    public static void main(String[] args) {
        //静态方法和非静态方法区别很大
        //静态方法: 方法的调用之和左边,定义的数据类型有关
        //非静态:重写
        A a = new A();
        a.test();//A


        //父类的引用指向了子类
        B b = new A();//子类重写了父类的方法
        b.test();//B





    }
}
/*
重写:需要有继承关系,子类重写父类的方法
   1.方法名必须相同
   2.参数列表必须相同
   3.修饰符:范围可以扩大:public > protected > default > private
   4.抛出的异常:范围,可以被缩小,但不能扩大:

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

   为什么要重写:
     1.弗雷德功能,子类不一定需要,或者不一定满足
 */

多态

  • 同一方法可以根据发送对象的不同而采取多种不同的行为方式
  • 方法或对象具有多种形态,是面向对象的第三大特征,多条是建立在封装和继承基础之上的
  • 一个对象的实际类型是确定的,单可以指向对昂的引用类型有很多(父类,有关系的类)
  • 多态的具体体现:
    • 方法的多态 重新二和重载就体现多态
    • 对象的多态:
      • 一个对象的编译类型和运行类型可以不一致
      • 编译类型在定义对象时,就确定了,不能改变
      • 运行类型是可以变化的
      • 编译类型看定义是 等号的左边,运行类型看等号的右边
  • 注意:多态是方法的多态,属性没有多态性
    • 前提:两个对象(类)存在继承关系
    • 多态的向上转型
    • 本质:父类的引用指向了子类的对象
    • 语法:父类类型 引用名 = new子类类型();
    • 特点:编译类型看左边,运行类型看右边
    • 可以调用父类中的所有成员,需要遵循访问权限,不能调用子类中的特有成员,最终运行效果看子类的具体实现
  • 多态向上转型调用方法的规则如下:
    • 可以调用父类中的所有成员(须遵循访问权限)
    • 但是不能掉哟个子类的特有的成员
    • 因为在编译阶段,能调用那些成员,是由编译类型来决定的
    • 最终运行效果看子类(运行类型)的具体实现,即调用方法时,按照从子类(运行类型)开始查找方法
    • 然后调用,跟方法调用的规则一致
  • 多态向下转型:
    • 语法:子类类型 引用名 = (子类类型)父类引用;
    • 只能强转父类的引用,不能强转父类的对象
    • 要求父类的引用必须指向的时当前忙于表类型的对象
    • 向下转型后可以调用子类类型中所有的成员
public class Person {
    public  void run(){
        System.out.println("run");
    }

}
/*
多态注意事项:
    1.多态是方法的多态,属性没有多态
    2.子类和父类,有联系  类型转换异常  ClassCastException!
    3.存在条件: 继承关系,方法要重写,父类引用指向子类对象!Father f1 = new Son();

        无法被重写的方法:
        1.static 方法,属于类,它不属于实例
        2.final  常量
        3.private方法
 */
public class Student extends  Person{
    public void run(){
        System.out.println("son");
    }
    public void eat(){
        System.out.println("eee");
    }
    public void go(){
        System.out.println("go");
    }
}

public class Application {
    public static void main(String[] args) {
        //一个对象的实际类型是确定的
        //new  Student();
        //new Person();
        //可以指向的引用类型就不确定了:父类的引用指向子类

        // Student 能调用的方法都是自己的或者继承父类的
        Student s1 = new Student();
        //Person 父类型,可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();


        //对象能执行那些方法,主要看对象左边的类型,和右边那关系不大!
        //如果这个方法只有父类有,那么父类和子类都可以调用
        //如果这个方法只有子类有,则父类需要强制类型转换后才可以调用
        //如果这个方法,父类和子类都有的情况下,但是输出的结果不同,优先调用子类的
        s2.run();//子类重写了父类的方法,执行了子类的方法
        s1.run();
        ((Student)s2).eat();//强制类型转换



    }
}
  • 属性没有重写之说,属性的值看编译类型

  • public class A {//父类
        public int count = 10;//属性
    }
    class B extends  A{//子类
        public  int count = 20;//属性
    }
    
  • public class Test1 {
        public static void main(String[] args) {
            A a = new B();//向上转型
            System.out.println(a.count);//10,跟编译类型有关,和运行类型无关
            B b = new B();
            System.out.println(b.count);//20,编译类型时B,
    
        }
    }
    
  • instanceof(类型转换)引用类型:用于判断对象的运行类型是否位xx类型或xx类型的子类型

public class Application1 {
    public static void main(String[] args) {

        //Object > Person > Student
        //Object > Person > Teacher
        //Object > String
        Object object = new Student();

        //System.out.println(X  instanceof Y); //能不能编译通过,主要看X跟Y有没有父子关系
        //创建对象是以子类
        System.out.println(object instanceof Student);//true
        System.out.println(object instanceof Person);//true
        System.out.println(object instanceof Object);//true
        //Teacher是Person的另一个子类,跟Student不存在继承关系,所以输出的结果是false
        System.out.println(object instanceof Teacher);//false
        //Sting类是Object的一个子类,与Student不存在继承关系
        System.out.println(object instanceof String);//false

        System.out.println("=======================");
        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
        //Teacher是Person的另一个子类,跟Student不存在继承关系,所以输出的结果是false
        System.out.println(person instanceof Teacher);//false
        //编译报错,Person和String同为Object的子类,同级之间不能转换
        //System.out.println(person instanceof String);

        System.out.println("================");
        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
        //编译错误,Student和Teacher同为Person的子类,同级,同级之间不能相互转换
        //System.out.println(student instanceof Teacher);
        //String是Object的子类,与Student没有继承关系
        //.out.println(student instanceof String);


    }
}
public class Application2 {
    public static void main(String[] args) {
        //类型之间的转换: 父类   子类
        //高                     低
        Person person = new Student();

        //需要将person这个对象转换为Student类型,我们就可以使用Student类型的方法了
        Student person1 = (Student) person;
        person1.go();
        ((Student) person).go();

        //子类转换为父类,可能会丢失自己本来的一些方法
        Student student = new Student();
        student.go();
        Person person2 = student;

    }
}


/*
1.父类引用指向子类的对象
2.把子类转换为父类,向上转型
3.把父类转换为子类,向下转型:强制转换
4.方便方法的调用,减少重复的代码,是代码变得简洁

抽象:封装、继承、多态   抽象类:接口······
 */
java的动态绑定机制
  1. 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

    package dynamic;
    
    public class Test {
        public static void main(String[] args) {
            A a = new B();//向上转型
            System.out.println(a.sum());//当调用sum()方法时,先找运行类型B类中的sum方法,方法中调用属性遵循就近原则
            System.out.println(a.sum1());//当调用sum1()方法时,先找运行类型B 中的sum1()方法,如果没找到,
            //去父类中找,找到了就调用父类中的,但是sum1()方法中调用了getI()方法,所以还是遵循调用原则,先找运行类型B 中的
            //实现了动态绑定
            B a1 = (B) a;//向下转型
            System.out.println(a1.i);
        }
    
    }
    class A {
        public int i = 10;
        public int sum(){
            return i+20;
        }
        public int getI(){
            return i;
        }
        public int sum1(){
            return getI()+10;
        }
    }
    class B extends A{
        public int i = 20;
        public int sum(){
            return i+20;
        }
        public int getI(){
            return i;
        }
        public int sum1(){
            return getI()+10;
        }
    }
    
    
  2. 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用

import poly.polyarr.Person;

public class Test1 {
    public static void main(String[] args) {
        Person[] person = new Person[5];
        person[0] = new Person("jack",22);
        person[1] = new Student("小明",15,60.6);
        person[2] = new Student("小李",15,99.9);
        person[3] = new Teacher("老李",35,50000);
        person[4] = new Student("盛浩",28,90000);


        for (int i = 0; i < person.length; i++) {
            //Person[i]编译类型时Person,运行类型时根据实际情况由JVM来判断
            System.out.println(person[i].say());//动态绑定机制
            if ( person[i] instanceof Student) {//判断person[i]的运行类型是不是Student
                Student student = (Student)person[i];//向下转型
                //也可以用 ((Student)person[i]).say();
                student.study();
            } else if (person[i] instanceof  Teacher) {//判断person[i]的运行类型是不是Teacher
                Teacher teacher = (Teacher) person[i];//向下转型
                teacher.teach();
            }else if (person[i] instanceof Person) {
            }else {
                System.out.println("你的代码有误");
            }
        }

    }
}

package poly.polyarr;
//创建一个Person对象,两个Student对象和两个Teacher对象,统一放在数组中,并调用say方法
public class Person {//父类
    private String name;//姓名
    private int age;//年龄

    public Person(String name, int age) {//有参构造器
        this.name = name;
        this.age = 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;
    }
    public String say(){
        return  "姓名:"+name+" 年龄:"+age;
    }
}
class Teacher extends Person{//子类
    private double salary;

    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String say() {
        return super.say()+" 工资:"+salary;
    }
    public void teach(){
        System.out.println("教学生");
    }
}

class Student extends  Person{
    private double score;

    public Student(String name, int age, double score) {
        super(name, age);
        this.score = score;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }
    //重写父类的say方法
    @Override
    public String say() {
        return super.say()+" 成绩:"+score;
    }
    public void study(){
        System.out.println("学会儿");
    }
}


  1. 方法定义的形参类型位父类类型,实参类型允许为子类类型
package poly.polyparameter;

import poly.Master;

//测试类中添加一个方法showEmpAnnual(Employee e),实现获取任何员工对象的年工资
//并在main方法中调用该方法
//测试类中增加一个方法testWork,如果时普通员工,则调用work方法,如果是经理,则调用manage方法
public class PloyParameter {//父类

    public static void main(String[] args) {
        PloyParameter ployParameter = new PloyParameter();//创建对象方便引用方法
//        Manager li = new Manager("li",10000,2000);//创建经理对象
//        Ordinary liu = new Ordinary("liu", 5000);//创建普通员工对象
//        ployParameter.testWork(liu);
//        ployParameter.showEmpAnnual(liu);
//        ployParameter.testWork(li);
//        ployParameter.showEmpAnnual(li);
        Employee[] e = new Employee[2];//用多态数组的方式表示
        e[0] = new Manager("威思顿", 10000, 1500);
        e[1] = new Ordinary("赞稼", 5000);
        for (int i = 0; i < e.length; i++) {
            System.out.println(e[i]);
            ployParameter.showEmpAnnual(e[i]);
            ployParameter.testWork(e[i]);
        }
    }
        public void showEmpAnnual(Employee e) {//查看年薪
            System.out.println(e.getAnnual());
        }
        public void testWork (Employee e){//用来判定运行类型时那个子类,以此来决定调用那个方法
            if (e instanceof Manager) {//条件判断其运行类型是不是Manager
                ((Manager) e).manage();
            } else {
                ((Ordinary) e).work();
            }
        }

    }


package poly.polyparameter;
//包含姓名和月工资[private]。以及计算年工资getAnnual的方法
//普通员工和经理继承了员工,经理类多了奖金bonus属性和管理manage方法
//普通员工多了work方法,普通员工和经理类要求分别重写getAnnual方法
public class Employee {
    private String name;//名字
    private  double salary;//薪水
    public Employee(){}

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    public double getAnnual(){
        return salary*12;
    }
}

package poly.polyparameter;
//普通员工多了work方法
public class Ordinary extends Employee{//普通员工类,子类
    public Ordinary(String name, double salary) {
        super(name, salary);
    }
    public void work(){
        System.out.println("员工"+getName()+"工作了");
    }
    @Override
    public double getAnnual() {//重写父类的方法
        return super.getAnnual();
    }
}

package poly.polyparameter;
//经理类多了奖金bonus属性和管理manage方法
public class Manager extends Employee {//经理类,子类
    private double bonus;


    public Manager(String name, double salary, double bonus) {
        super(name, salary);
        this.bonus = bonus;
    }

    public double getBonus() {
        return bonus;
    }

    public void setBonus(double bonus) {
        this.bonus = bonus;
    }
    public void manage(){
        System.out.println("经理"+getName()+"进行了管理");
    }

    public double getAnnual(){
        return (getSalary()+bonus)*12;
    }
}

## 抽象类和接口

## 接口

- 普通类:只能具体实现
- 抽象类:具体实现和规范(抽象方法)都有
- 接口:只有规范  自己无法写方法   专业的约束!约束和实现分离:面向接口编程
- 接口就是规范,定义的是一组会泽,体现在现实世界中,“如果你是········则必须能····”的思想
- **接口的本质是契约**,就像我们的法律一样,制定好了大家都要遵守
- oo的精髓,是对对象的抽象,最能体现这一点的就是接口,为什么我们讨论设计模式以都只针对具备了抽象能力的语言,就是因为设计模式所研究的,实际上就是如何合理的去抽象
- 只有一个方法的接口叫做函数时接口,可以使用lambda表达式简化
- 抽象类的关键字是class,声明类的关键字是interface

```java
//interface   定义接口的关键字
public interface UserService {
    //接口中的所有定义的方法都是抽象的  public  abstract
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}
//抽象类:extends
//类可以通过implements实现接口
public class UserServiceImp1 implements UserService,TimeService{
    @Override
    public void add(String name) {

    }
    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }
    @Override
    public void timer() {

    }
}


public interface TimeService {
    void timer();
}

作用:
    1.约束
    2.定义一些方法,让不同的人实现
    3.public abstract  接口中的所有定义的方法都是抽象的
    4.public static final  在接口中定义常量
    5.接口不能被实例化~  ,接口中没有构造方法
    6.接口中可以通过implements实现多个接口
    7.在类中必须重写接口中的方法
    

内部类及oop实战

内部类

  • 内部了哦就是在一个类的内部再定义一个类,比如,A类中定义一个B类,那么B 类相对A 类来说就成为内部类,而A类相对B类来说就是外部类
    • 成员内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类
public class Outer {
    private  int id = 10;
    public void out(){
        System.out.println("这是外部类的方法");
    }

    public class  Inner{
        public void in(){
            System.out.println("这是内部类的方法");
        }

        //内部类可以获得外部类的私有属性
        public void getId(){
            System.out.println(id);
        }
    }
    //局部内部类
    public  void  method(){
        class inin{
            public void ininin(){

            }
        }
    }
    }


public class Test {
    
    public static void main(String[] args) {
        //匿名内部类:没有名字初始化类,不用将实例保存到变量中 
        new Apple().eat();
    }
    UserService userService = new UserService() {

        @Override
        public void hello() {

        }
    };
}


class Apple{
    public void eat(){
        System.out.println("1");
    }
}
interface UserService{
    void hello();
}
  • 58
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值