继承&抽象&多态&接口

面向对象思想:
    不同对象之间相互访问--》  new  对象().方法
    思想就是懒人思想,找人帮忙做
    面向对象三大特征:封装、继承、多态
 

1.继承

继承(Inheritance)是面向对象编程中的一种重要特性,它允许一个类(子类)继承另一个类(父类)的属性和方法。继承有助于实现代码重用和扩展,建立类之间的层次关系。在Java中,继承是通过使用`extends`关键字实现的。

public class 子类名 extends 父类名{

}

1.1继承特点

1. 子类可以继承父类的非私有成员(成员变量、成员方法)。这意味着子类可以拥有父类的方法和变量,并且可以在子类中直接使用它们,有助于实现代码重用,从而避免在各个子类中重复编写相同的代码。

2. 继承支持多层继承。在Java中,类是单继承的,即一个类只能有一个父类。但是,它支持多层继承,也就是说,一个类可以继承另一个类的子类,就形成儿子继承父亲,父亲继承爷爷的家谱。

3. 子类可以覆盖(Override)父类的方法。覆盖是指子类重新定义父类的方法,以实现不同的功能。这使得子类可以根据需求对父类的方法进行修改或扩展。

4. 继承有助于实现封装。通过继承,子类可以隐藏其内部实现,而只暴露公共接口给外部使用。这样可以提高代码的封装性和可维护性。

public class Father {
    private String name;
    private int age;

    int fu=100;

    int num=222;
    public Father() {
        System.out.println("我是父类的空参构造");
    }

    public Father(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("我是父类的全参构造");
    }

    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 void eat(){
        System.out.println("人要吃饭");
    }
    protected void makeMoney(){
        System.out.println("我要挣钱");
    }

}
public class Son extends Person {

    int num=111;

    int zi=50;
    public Son() {
        System.out.println("我是子类的空参构造");
    }

    public Son(String name, int age) {
        super(name, age);
        System.out.println("我是子类继承父类的全参构造");
    }

    public void a(int num){
        System.out.println(num);
    }
    public void b(int num){
        System.out.println(this.num);
    }
    public void c(int num){
        System.out.println(super.num);
    }
    @Override
    public void makeMoney(){
        System.out.println("能挣钱");
        System.out.println("赚了多少钱");
    }
}

1.2匿名对象(了解)


    创建对象时不给名字    new 类名();
    使用:new 类名().方法名
    使用场景:如果只是简单调用一些方法可以用,如果是给对象属性赋值就不可以

        //匿名Father类
        new Father().eat();
        new Father().setAge(16);//与后面的Father类对象无关,是重新new的
        System.out.println(new Father().getAge());

1.3继承中成员变量的访问特点

       1.变量不重名:
         如果new的是父类对象,只能调用父类的
         如果new的是子类对象,既能掉子类自己的,也能掉从父类继承的(非私有)
       2.变量重名:
          看等号左边是谁,先调用谁的成员,子类如果没有,找父类
       3.当子类中成员变量和局部变量跟父类中的成员变量重名
          this.成员变量:代表的是自己的成员变量
          super.成员变量:代表的是父类的成员变量

1.4继承中成员方法的访问特点

       1.不重名:
         如果new的是父类对象,只能调用父类的
         如果new的是子类对象,既能调子类自己的,也能调用父类继承的(非私有)
       2.重名:
         看new的是谁就先调用谁的方法,子类没有就找父类

        Son son1=new Son();
        System.out.println(son1.num);

        Father fa = new Father();
        int i = fa.fu;//父类对象调父类变量
        System.out.println(i);
        int ii = son1.zi;//子类对象调子类变量
        System.out.println(ii);
        int iii = son1.fu;//子类对象调父类变量
        System.out.println(iii);

        fa.eat();//父类对象调父类方法
        son1.eat();//子类对象调父类变量
        fa.makeMoney();//父类对象调父类变量
        son1.makeMoney();//子类对象调子类变量
        //fa.a();//父类不能调用子类方法
        son1.a(999);//子类对象调子类变量
        son1.b(999);
        son1.c(999);
        

1.5方法的重写

       1.方法的重载 (overload)方法名相同,参数列表不同
       2.方法的重写 (override)子类和父类有一样的方法。注解: @override --》 检测该方法是不是重写的方法前提:必须有子父类继承关系
       3.注意事项
             a.子类方法覆盖父类方法,必须保证权限大于等于父类权限。
                   public->protected->默认的->private)
             b.子类方法覆盖父类方法,返回值类型、函数名和参数列表必须一模一样
             c.私有方法不能被重写(父类私有方法是不能被子类继承)

       4.重写场景
            子类想要对父类中的方法的功能进行增强

  注意:构造方法能重写吗?
          构造方法方法名等于类名
          父类名不能等于子类名字
          所以不能重写

1.6 super和this

super:代表的是父类对象
1.每一个构造方法中,第一行默认有一个super () --》代表的是父类的构造方法创建子类对象之前会创建父类对象。
2.
    调用父类的成员变量-->在子类中super.成员变量名
    调用父类的成员方法-->在子类中super.方法名 (参数)
    调用父类的构造方法-->在子类构造方法中 super() 或者super(参数)
this:
    a.this调用本类构造方法的时候 需要写在构造方法的第一行
    b.在构造方法中,this和super不能同时存在
    c.不要用this在有参和空参之间来回调用 (死循环)

2.抽象

1.抽象:说不明道不明
2.注意事项:
  A。将所有公共的方法抽取出来,每个类实现方式不同,所有抽出来的方法并不能确定功能。这个方法就是抽象方法。
  B.  抽象方法所在的类 必须是抽象类。
  C. 抽象类中不一定非得有抽象方法,构造方法,普通方法,静态方法
  D.抽象方法中不能new对象。需要通过子类去实现抽象方法。
  
 3. 使用:
  a.定义抽象类:
  修饰符 abstract class 类名{
  }
  b.定义抽象方法:
   修饰符  abstract  返回值类型 方法名(参数);
  c.创建子类对象   继承父类,重写抽象方法。
  d.创建子类对象  调用子类重写方法。

public abstract class Animal {

//定义一个抽象方法
    public  abstract  void eat();

}

public class Dog extends Animal {
//重写eat方法
    public void eat(){
        System.out.println("狗吃肉");
    }
}

public class Test {
    public static void main(String[] args) {
        Dog dog =new Dog();
        dog.eat();
    }
}

3.接口

1.概念:就是一种标准,规范。
2.接口的定义格式;
    interface  接口名{}

public interface USB {
}

3.1接口中的抽象方法

1.定义格式;
     即时不写  abstract  默认也有
     public  abstract   返回值类型 方法名(参数);
2.使用:
    a.定义一个实现类 , 实现接口--->    类名  implements 接口名
    b.必须实现所有抽象方法 
    c.创建实现类对象(接口不能直接new对象),调用重写的方法。
    

//USB接口
public interface USB {

    public abstract  void open();

    public void close();

    void method();


}
//实现类1
public class Mouse implements USB{


    @Override
    public void open() {
        System.out.println("我打开了");
    }

    @Override
    public void close() {
        System.out.println("我关闭了");
    }

    @Override
    public void method() {
        System.out.println("w shi ge fangfa");
    }
}
//实现类2
public class Pc implements USB{
    @Override
    public void open() {

    }

    @Override
    public void close() {

    }

    @Override
    public void method() {

    }
}

3.2抽象类和接口的区别

1. 定义:抽象类:一般作为父类来使用,可以包含  构造方法 , 成员变量, 普通方法,静态方法,抽象方法,它用于作为其他类的基类。接口是一个纯粹的规范,功能的合集,它只包含抽象方法和常量的定义,用于描述类应该具有的行为。

2. 实现方式:一个类只能继承一个抽象类,但可以实现多个接口。这意味着一个类可以通过继承抽象类来获得一些共享的实现代码,同时通过实现接口来满足多个规范。

3. 构造函数:抽象类可以有构造函数,而接口不能有构造函数。因为接口只是一种规范,不涉及对象的实例化。

4. 默认实现:抽象类可以包含具体的方法实现,子类可以直接继承这些实现。接口只能定义抽象方法,不包含具体的实现,子类必须实现接口中定义的所有方法。

5. 使用情况:抽象类适用于具有共享代码和行为的类层次结构,它可以提供一些通用的实现。接口适用于描述类应该具有的行为,提供一种规范,使得不同的类可以实现相同的接口,从而实现多态性。

总的来说,抽象类更适合于类层次结构的设计,而接口更适合于定义类的行为规范。在实际应用中,需要根据具体的需求和设计目标来选择使用抽象类还是接口。

3.3接口特点(了解中的了解)

1.接口可以多实现。(一个类可以同时实现多个接口)-->必须要重写所有接口中的所有抽象方法。
    类  implements  接口1,接口2
2.接口可以多继承   (一个接口可以同时继承一个或者多个接口)
   接口 extends  接口1,接口2.
3.一个类可以继承一个父类的同时实现一个或多个接口   (类 dxtends 父类 implements  接口1,接口2)

4.多态

1.概述:一个事物的不同形态:
    cut  这个单词 理发店是剪头发     但是拍电影就是停止。
2.条件:
    a.子父类继承关系(接口,实现关系)
    b.必须有方法的重写
    c.父类引用指向子类--->   父类   对象名=  new 子类();
                         接口名 接口 =new   实现类();
     只能调用重写方法,不能调用子类特有方法

public class Test2 {

    public static void main(String[] args) {
        //多态写法
        USB  usb =new Mouse();
        usb.open();

        usb=new Pc();
        //正常写法
	    Mouse mouse =new Mouse();
        mouse.open();

        Pc  pc =new Pc();
    }
}

4.1多态中成员变量和成员方法的访问特点(重点)

 * 多态调用成员变量   看等号左边是谁就调用谁的
 * 多态调用成员方法 ,  看new的是谁就调用谁。如果子类没有去父类找

 Animal animal=new Dog();
 System.out.println(animal.a);
 animal.eat();//new的是Dog,所以调用Dog的eat方法,如果Dog中没有该方法才调用父类的
 //如果animal.成员变量则是Animal类中的成员变量

4.2多态的转型(重点)

1.向上转型        eg:父类 对象名  =new 子类();
    父类引用指向子类对象
    弊端:不能直接调用子类的特有方法。

2.向下转型        eg:子类  对象名= (子类)父类对象名--》

   向下转型-》   可以调用子类特有方法。
   就像 double b =10;
    int i =b   ;--- 报错,强转 --》 int i  =(int)b;

3.问题:
   不存在关系的两个转换会报错。
           Animal  animal =new Dog();
         //animal.eat();
         //animal.lookDoor(); 不能调用特有方法;
        
        Cat cat =(Cat)animal;//此时该animal是Dog类对象
        cat.catchMouse();

    会报错ClassCastException: Dog cannot be cast to Cat
    
    类型转换异常  猫不能转成狗。
4.如何解决。
    instanceof  方法判断
   使用:
   对象名   instanceof  类名---  》  判断前面的是否属于后面的类型。

5.封装

封装(Encapsulation):封装是指将数据和对数据的操作封装在一个单元中,通过定义类来实现。类将数据和方法封装在一起,隐藏了内部实现细节,只暴露必要的接口供外部使用。这样可以保护数据的完整性和安全性,同时提高代码的可维护性和复用性。

(之前我发布的文章中有封装具体介绍)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值