【?如何理解面向对象和面向过程】

2023-12-16 23:34:56

在这里插入图片描述

典型理解


面向过程把问题分解成一个一个步骤,每个步骤用函数实现,依次调用即可。

我们在进行面向过程编程的时候,不需要考虑那么多,上来先定义一个函数,然后使用各种诸如if-else、for-each等方式进行代码执行。最典型的用法就是实现一个简单的算法,比如实现冒泡排序。


面向对象将问题分解成一人一个步骤,对每个步骤进行相应的抽象,形成对象,通过不同对象之间的调用,组合解决问题。

就是说,在进行面向对象进行编程的时候,要把属性、行为等封装成对象,然后基于这些对象及对象的能力进行业务逻辑的实现。比如想要造一辆车,上来要先把车的各种属性定义出来,然后抽象成一个Car类。

面向对象有封装、继承、多态二大基本特征,和单一职责原则、开放封闭原则、Liskov替换原则、依赖倒置原则和 接口隔离原则等五大基本原则。

?扩展知识仓

?面向对象的三大基本特征

三大基本特征:封装继承多态

?封装

**封装就是把现实世界中的客观事物抽象成一个Java类,然后在类中存放属性和方法。**比如:封装一个汽车类,其中包含了发动机、轮胎、底盘等属性,并且有启动、前进等方法。

//定义一个汽车Car类
public class Car {  
    // 私有变量  
    private String brand; // 品牌  
    private String model; // 型号  
    private int year; // 生产年份  
    private String color; // 颜色  
    private double price; // 价格  
    private Engine engine; // 引擎  
    private Transmission transmission; // 变速器  
    private boolean isOwned; // 是否拥有  
      
    // 构造方法  
    public Car(String brand, String model, int year, String color, double price, Engine engine, Transmission transmission) {  
        this.brand = brand;  
        this.model = model;  
        this.year = year;  
        this.color = color;  
        this.price = price;  
        this.engine = engine;  
        this.transmission = transmission;  
        this.isOwned = false;  
    }  
      
    // 公共方法:获取品牌  
    public String getBrand() {  
        return brand;  
    }  
      
    // 公共方法:设置品牌  
    public void setBrand(String brand) {  
        this.brand = brand;  
    }  
      
    // 公共方法:获取型号  
    public String getModel() {  
        return model;  
    }  
      
    // 公共方法:设置型号  
    public void setModel(String model) {  
        this.model = model;  
    }  
      
    // 公共方法:获取生产年份  
    public int getYear() {  
        return year;  
    }  
      
    // 公共方法:设置生产年份  
    public void setYear(int year) {  
        this.year = year;  
    }  
      
    // 公共方法:获取颜色  
    public String getColor() {  
        return color;  
    }  
      
    // 公共方法:设置颜色  
    public void setColor(String color) {  
        this.color = color;  
    }  
      
    // 公共方法:获取价格  
    public double getPrice() {  
        return price;  
    }  
      
    // 公共方法:设置价格  
    public void setPrice(double price) {  
        this.price = price;  
    }  
      
    // 公共方法:获取引擎对象  
    public Engine getEngine() {  
        return engine;  
    }  
      
    // 公共方法:设置引擎对象  
    public void setEngine(Engine engine) {  
        this.engine = engine;  
    }  
      
    // 公共方法:获取变速器对象  
    public Transmission getTransmission() {  
        return transmission;  
    }  
      
    // 公共方法:设置变速器对象  
    public void setTransmission(Transmission transmission) {  
        this.transmission = transmission;  
    }  
      
    // 公共方法:判断是否拥有该汽车,如果拥有则返回true,否则返回false。在构造函数中,isOwned被设置为false,表示初始状态为未拥有。可以在后续操作中改变其状态。  
    public boolean isOwned() {  
        return isOwned;  
    }  
}

?继承

像现实世界中儿子可以继承父亲的财产、样貌、行为等一样,编程世界中也有继承,继承的主要目的就是为了复用。子类可以继承父类,这样就可以把父类的属性和方法继承过来。

比如:Dog类,可以继承Animal类,继承过来嘴巴,颜色、等属性,吃东西、奔跑等行为。

// Animal类  
public class Animal {  
    private String name;  
      
    public Animal(String name) {  
        this.name = name;  
    }  
      
    public String getName() {  
        return name;  
    }  
      
    public void setName(String name) {  
        this.name = name;  
    }  
      
    // 抽象方法,需要子类实现  
    public abstract void makeSound();  
}  
  
// Dog类,继承自Animal类  
public class Dog extends Animal {  
    private String breed;  
      
    public Dog(String name, String breed) {  
        super(name); // 调用父类的构造函数  
        this.breed = breed;  
    }  
      
    public String getBreed() {  
        return breed;  
    }  
      
    public void setBreed(String breed) {  
        this.breed = breed;  
    }  
      
    // 实现父类的抽象方法  
    @Override  
    public void makeSound() {  
        System.out.println("汪汪!");  
    }  
}

在这个例子中,Animal类是一个抽象类,定义了一个抽象方法makeSound,它需要由子类来实现。Dog类继承了Animal类,并实现了makeSound方法,因此它是一个具体的类。在Dog类中,我们还添加了一个新的属性breed和一个相应的方法来获取和设置该属性的值。

?多态

多态是指在父类中定义的方法被子类继承之后,可以通过重写,使得父类和子类具有不同的实现,这使得同一个方法在父类极其各个子类中具有不同的含义。

// 定义一个接口,名为Animal  
public interface Animal {  
    // 定义一个抽象方法,用于发出动物的叫声  
    void makeSound();  
}  
  
// 定义一个类,名为Dog,实现Animal接口  
public class Dog implements Animal {  
    // 重写makeSound方法,实现狗的叫声  
    @Override  
    public void makeSound() {  
        System.out.println("汪汪!");  
    }  
}  
  
// 定义一个类,名为Cat,实现Animal接口  
public class Cat implements Animal {  
    // 重写makeSound方法,实现猫的叫声  
    @Override  
    public void makeSound() {  
        System.out.println("喵喵!");  
    }  
}  
  
// 定义一个类,名为Zoo,包含一个Animal类型的成员变量  
public class Zoo {  
    // 定义一个Animal类型的成员变量,可以是任何实现Animal接口的类对象  
    private Animal animal;  
      
    // 构造函数,接受一个Animal类型的参数,用于初始化animal成员变量  
    public Zoo(Animal animal) {  
        this.animal = animal;  
    }  
      
    // 定义一个方法,让动物发出叫声  
    public void letAnimalMakeSound() {  
        // 使用多态性,调用animal对象的makeSound方法,实现不同的叫声  
        animal.makeSound();  
    }  
}  
  
// 在主函数中测试多态性的实现  
public static void main(String[] args) {  
    // 创建一个Dog对象  
    Dog dog = new Dog();  
    // 使用Dog对象创建一个Zoo对象  
    Zoo zoo = new Zoo(dog);  
    // 调用Zoo对象的letAnimalMakeSound方法,让动物发出叫声  
    zoo.letAnimalMakeSound(); // 输出 "汪汪!"  
      
    // 创建一个Cat对象  
    Cat cat = new Cat();  
    // 使用Cat对象创建一个Zoo对象  
    zoo = new Zoo(cat);  
    // 调用Zoo对象的letAnimalMakeSound方法,让动物发出叫声  
    zoo.letAnimalMakeSound(); // 输出 "喵喵!"  
}

在这个例子中,我们定义了一个Animal接口和两个实现了该接口的类Dog和Cat。我们还定义了一个Zoo类,其中包含一个Animal类型的成员变量。在Zoo类中,我们使用多态性来调用Animal对象的makeSound方法,实现了不同的叫声。在主函数中,我们分别使用Dog和Cat对象创建了两个Zoo对象,并调用了它们的letAnimalMakeSound方法,输出了不同的叫声。

?为什么Java不支持多继承?

因为如果要实现多继承,就会像C++中一样,存在菱形继承的问题,C++为了解决菱形继承问题,又引入了虚继承。因为支持多继承,引入了菱形继承问题,又因为要解决菱形继承问题,引入了虚继承。而经过分析,人们发现我们其实真正想要使用多继承的情况并不多。所以,在Java 中,不允许“多继承”,即一个类不允许继承多个父类。

除了菱形的问题,支持多继承复杂度也会增加。一个类然承了多个父类,可能会继承大量的属性和方法,导致类的接口变得庞大、难以理解和维护。此外,在修改一个父类时,可能会影响到多个子类,增加了代码的耦合度。

在Java 8以前,接口中是不能有方法的实现的。所以一个类同时实现多个接口的话,也不会出现C++中的歧义问题。因为所有方法都没有方法体,真正的实现还是在子类中的。但是,Java 8中支持了默认函数(defaultmethod),即接口中可以定义一个有方法体的方法了。

而又因为Java支持同时实现多个接口,这就相当于通过implements就可以从多人接口中继承到多人方法了,但是,Java8中为了避免菱形继承的问题,在实现的多个接口中如果有相同方法,就会要求该类必须重写这个方法。

?菱形继承问题

Java的创始人James Gosling曾经回答过,他表示:

"Java之所以不支持一个类继承多个类,主要是因为在设计之初我们听取了来自C++和Obiective-C等阵营的人的意见。因为多继承会产生很多歧义问题。”

Gosling老人家提到的歧义问题,其实是C++因为支持多继承之后带来的菱形继承问题。

假设我们有类B和类C,它们都继承了相同的类A。另外我们还有类D,类D通过多重继承机制继承了类B和类C.。

在这里插入图片描述
这时候,因为D同时继承了B和C,并且B和C又同时继承了A,那么,D中就会因为多重继承,继承到两份来自A中的属性和方法。

这时候,在使用D的时候,如果想要调用一个定义在A中的方法时,就会出现歧义。

因为这样的继承关系的形状类似于菱形,因此这个问题被形象地称为菱形继承问题。

而C++为了解决菱形继承问题,又引入了虚继承

因为支持多继承,引入了菱形继承问题,又因为要解决菱形继承问题,引入了虚继承。而经过分析,人们发现我们其实真正想要使用多继承的情况并不多。

所以,在Java 中,不允许“声明多继承”,即一个类不允许继承多个父类。但是Java 允许“实现多继承”,即个类可以实现多个接口,一个接口也可以继承多个父接口。由于接口只允许有方法声明而不允许有方法实现(Java 8之前),这就避免了 C++ 中多继承的歧义问题。

?Java 8 中的多继承

Java不支持多继承,但是是支持多实现的,也就是说,同一个类可以同时实现多个接口。

我们知道,在Java 8以前,接口中是不能有方法的实现的。所以一个类同时实现多个接口的话,也不会出现C++中的歧义问题。因为所有方法都没有方法体,真正的实现还是在子类中的。

💡那么问题来了?

Java 8中支持了默认函数 (default method ),即接口中可以定义一个有方法体的方法了。

public interface Pet {
	public default void eat() {
		System.out.println("Pet Is Eating");
	}
}

而又因为Java支持同时实现多个接口,这就相当于通过implements就可以从多个接口中继承到多人方法了,这不就是变相支持了多继承么。

那么,Java是怎么解决菱形继承问题的呢? 我们再定义一个哺乳动物接口,也定义一个eat方法。

public interface Mammal {
	public default void eat() {
		System.out.println("Mammal Is Eating");
	}
}

然后定义一个Cat,让他分别实现两个接口:

public class Cat implements Pet,Mammal {
	
}

这个时间编译会报错:

error: class Cat inherits unrelated defaults for eat() from types Mammal and Pet

这个时候,就要求Cat类中,必须重写eat()。

public class Cat implements Pet,Mammal {
	@Override
	public void eat()  {
		System.out.println("Cat Is Eating");
	}
}

所以可以看到,Java并没有帮我们解决多继承的歧义问题,而是把这个问题留给开发人员,通过重写方法的方式自己解决。

?面向对象的五大基本原则?

博客 : 设计模式

五大基本原则: 单一职责原则(Single-Responsibility Principle) 、开放封闭原则(Open-Closedprinciple) 、Liskov替换原则 (Liskov-Substituion Principle) 、依赖倒置原则(Dependency-InversionPrinciple)和接门隔离原则(Interface-Segregation Principle)。

单一职责原则 : 一个类最好只做一件事

开放封闭原则 : 对扩展开放、对修改封闭

里氏替换原则 : 子类必须能够替换其基类

依赖倒置原则 : 程序要依赖于抽象接口,而不是具体的实现

接口隔离原则 : 使用多个小的专门的接口,而不要使用一个大的总接口

文章来源:https://blog.csdn.net/Java_Yangxiaoyuan/article/details/135038728
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。