面向对象的三大特征

面向对象三大特征:封装,继承,多态

封装

先看下封装的英语解释:encapsulation:the process of enclosing (封闭的过程 )

JAVA中的封装就是隐藏具体的实现,把不希望暴漏出来方法和属性隐藏起来,只暴露出需要对外提供的信息。

例如微信,微信把自己的实现方式隐藏起来了,我们并不知道微信底层是怎么运作的的。微信只是通过图形化的界面为用户提供各种功能。

JAVA中实现封装的方法就是权限控制。权限控制分为四级:private, protected, default, public。

publicprotecteddefaultprivate
同一个类YesYesYesYes
同一个包YesYesYes
不同包的子类YesYes
不同包的无关类Yes

继承

基本概念

继承可以理解为is-a的关系,它做的就是将不同类的的相同的特征抽象成一个新类也就是父类,然后让这些类继承父类,成为这个父类的子类。JAVA中子类可以访问父类中用public和protected修饰的属性和方法,从而达到减少代码冗余的目的。继承还是多态的基石。另外需要注意的一点是JAVA是单继承的,也就是说一个子类只能有一个父类,一个父类可以有多个子类。

例如:我们有Cat和Dog两个类,他们有相同的属性(name)和方法(work)。我们可以从相同的属性中抽象出一个新类Pets

public class Cat {

    public String name;
    
    public Cat(String name) {
        this.name = name;
    }
    
    public void work() {
        System.out.println("走两步");
    }

    public void cleanSelf() {
        System.out.println("用爪子梳理毛发");
    }

}
public class Dog {

    public String name;

    public Dog(String name) {
        this.name = name;
    }
    
    public void work() {
        System.out.println("走两步");
    }
    
    public void eatShit() {
        System.out.println("真香");
    }

}
public class Pets {

    protected String name;

    public Pets(String name) {
        this.name = name;
    }

    public void work() {
        System.out.println("走两步");
    }

}
代码实现

然后我们可以把Pets当作Cat和Dog的父类来重写这两个类。

继承的语法:

public class A extends B {
	// A类继承了B类
}

重写Cat, Dog如下,super这个关键子的作用是调用父类中的方法或属性,spuer()这种写法代表的是调用父类的构造器。

public class Cat extends Pets {

    public Cat(String name) {
        super(name);
    }

    public void cleanSelf() {
        System.out.println("用爪子梳理毛发");
    }

}
public class Dog extends Pets {

    public Dog(String name) {
        super(name);
    }

    public void eatShit() {
        System.out.println("真香");
    }

}
初始化过程

在创建一个子类的实例时,会先创建一个父类的实例,然后才创建子类的实例,并用子类中的spuer关键字引用父类的实例。

image-20200901151251961

抽象类(Abstract关键字)

有时,父类方法的具体实现需要子类来实现。例如Cat和Dog都会吃东西,抽象到父类就是eat方法,但是Cat吃的时猫粮,Dog吃的是狗粮,这个方法的具体实现时由子类决定的。这时候就可以用到abstract关键字。

abstract可以修饰类和方法。

  1. 修饰类时:代表这个类是抽象类,不可以为这个类创建对象,例如下面的Pets类,不可以用new Pets()创建对象
  2. 修饰方法时:代表这个方法是抽象方法,不能在这个类中实现,需要子类来实现这个方法。有抽象方法的类必须是抽象类。

类如我们在Pets类中添加eat()的抽象方法:

public abstract class Pets {

    protected String name;

    public Pets(String name) {
        this.name = name;
    }

    public void work() {
        System.out.println("走两步");
    }

    public abstract void eat();

}

这时,我们就需要在子类中实现这个方法,不然编译器会报错。

public class Cat extends Pets {

    public Cat(String name) {
        super(name);
    }

    @Override
    public void eat() {
        System.out.println("吃猫粮");
    }

    public void cleanSelf() {
        System.out.println("用爪子梳理毛发");
    }

}
方法的重写

父类已经实现的方法,子类可以重新实现这个方法。

例如Pets类中的work()方法已经实现了,但是dog类不想用父类中走路的方法走路,那么他就可以重写这个方法

public class Dog extends Pets {

	...

    @Override
    public void work() {
        System.out.println("走四步");
    }

    ...

}

这样再用Dog类的对象调用work()时,会打印走四步,而不是Pets类中的走两步

多态(以继承为例,通过接口实现的多态和继承类似)

多态:是指同一行为,具有多个不同表现形式。

例如Cat和Dog都会eat(), 但是Cat吃的是猫粮。而Dog吃的是狗粮。

多态的好处要结合向上转型才能体现出来。

向上转型和向下转型
向上转型

向上转型是指从子类转成父类。如下面的代码所示

public class Main {

    public static void main(String[] args) {
        Cat c = new Cat("a");
        Pets p = c;
        p.eat();
		System.out.println(p.getClass().getSimpleName()); // 打印类名
    }

}

运行结果如下。从运行结果可以到,Cat类的对象可以转换成Pets类型,但是当调用eat()方法实际上调用的还是Cat类里的eat()方法。对象p的实际类型还是Cat类。也就是说,我们可以把把一只猫当作一个宠物来看,但是它实际上还是一只猫。

吃猫粮
Cat

Process finished with exit code 0
向下转型

向下转型是指父类对象转成子类对象;如下代码所示:

public class Main {

    public static void main(String[] args) {
        Cat cat_1 = new Cat("a");
        Pets p = cat_1;
        Cat cat_2 = (Cat) p;
        p.eat();
        System.out.println(cat_2.getClass().getSimpleName());
    }

}

需要注意的是父类对象必须实际上是子类对象才能向下转型成子类对象。也就是说宠物必须实际上是一只猫,才能转型成猫。否则在运行时会报错。

例如把一个实际上时Cat的Pets对象转成Dog:

public class Main {

    public static void main(String[] args) {
        Cat cat_1 = new Cat("a");
        Pets p = cat_1;
        Dog d = (Dog) p;
        d.eat();
    }

}

会报如下错误:

Exception in thread "main" java.lang.ClassCastException: class Cat cannot be cast to class Dog (Cat and Dog are in unnamed module of loader 'app')
	at Main.main(Main.java:18)

Process finished with exit code 1

为了程序运行期间发生这种错误,JAVA提供了instanceof关键字来判断对象的实际类型,例如判断是否是Cat类:if (p instanceof Cat)

所以上一段代码可以改成:

public class Main {

    public static void main(String[] args) {
        Cat cat_1 = new Cat("a");
        Pets p = cat_1;
        if (p instanceof Dog) {
            Dog d = (Dog) p;
            d.eat();
        }
        else if (p instanceof Cat) {
            Cat cat2 = (Cat) p;
            cat2.eat();
        }
    }

}
多态的使用

当我们给Cat和Dog喂东西吃的时候,我们不需要关心他们是怎么吃的,我们只需要知道他是宠物,需要吃东西就可以了。也就是说我们只需要考虑到Pets这一层就可以了。

代码如下:

public class Main {

    public static void feedPets(Pets pets) {
        pets.eat();
    }

    public static void main(String[] args) {
        Cat cat = new Cat("cat");
        Dog dog = new Dog("dog");
        System.out.println("准备食物");
        feedPets(cat);
        feedPets(dog);
    }

}

运行结果

准备食物
吃猫粮
吃狗粮

Process finished with exit code 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值