java工程师成神之路从零开始学习(面向对象的核心概念)


以下内容都是我跟着《深入理解java核心技术》这本书,一边学习一边抄录的内容。单纯的只是为了学习、巩固自己的知识点。

2.1 重载和重写

1.定义

重载:在同一个类中,多个函数或者方法有相同的名称,但是参数列表不同,这样的同名不同参数的函数或者方法,互相称之为重载函数或者重载方法。

重写:在Java中的子类与父类中,有两个名称和参数列表都相同的方法,由于它们具有相同的方法签名,所以子类中的新方法将覆盖父类中的原有方法。

区别 重载 重写
英文 Overloading Overriding
定义 方法名称相同,参数的类型或个数不同 方法名称、参数类型、返回值类型全部相同
权限 对权限没要求 被重写的方法不能拥有更严的权限
范围 发生在一个类中 发生在继承类中

2.重载需要满足以下条件和要求

  • 被重载的方法必须改变参数列表。
  • 被重载的方法可以改变返回类型。
  • 被重载的方法可以改变访问修饰符。
  • 被重载的方法可以声明新的或者更广的检查异常。
  • 方法能够在同一类中或者在一个子类中被重载。

3.重写需要满足以下条件和要求

  • 参数列表必须完全与被重写方法的参数列表相同。
  • 返回类型必须完全与被重写方法的返回类型相同。
  • 访问级别的限制性一定不能比被重写方法的限制性强。
  • 访问级别的限制性可以比被重写方法的限制性弱。
  • 重写方法一定不能抛出新的检查异常或比被重写的方法声明的检查异常有更广泛的检查异常。
  • 重写的方法能够抛出更少或更有限的异常(也就是说,被重写的方法声明了异常,但重写的方法可以什么也不声明)。
  • 不能重写被标示为final的方法。
  • 如果不能继承一个方法,则不能重写这个方法。

4.重写和重载的区别

区别 重载 重写
英文 overloading overiding
定义 方法名称相同,参数的类型或个数不同 方法名称、参数类型、返回值类型全部相同
权限 对权限没要求 被重写的方法不能拥有更严的权限
范围 发生在一个类中 发生在继承类中

2.2 多态

2.2.1 什么是多态

多态是一种面向对象编程中的概念,它指的是在一个程序中,多个对象可以共享相同的方法名称,但是在不同的对象中执行的代码不同。这种技术允许我们创建一个抽象类型,并定义其行为,然后在具体的子类中实现这些行为。在运行时,根据对象的类型,会调用相应的代码实现。

多态可以帮助我们把代码更好地组织,并使程序具有更好的可扩展性。在实际应用中,多态主要通过虚拟函数(virtual function)和抽象类(abstract class)实现。

1.特设多态

特别多态是指一种比较特殊的多态形式,它在编程语言中通常是通过特定的语法或技术实现的。特别多态允许在运行时动态的改变对象的类型,从而允许对象使用不同的行为实现。

在不同的编程语言中,特别多态的实现方式不尽相同。例如,在动态语言(如 Python)中,可以在运行时动态改变对象的类型,使用不同的行为实现。而在静态语言(如 Java)中,通常需要使用接口或抽象类来实现特别多态。

2.参数多态

参数多态是指在程序设计中,一个函数或方法可以接受不同类型的参数,并对它们进行相同的处理。这种技术的目的是使程序更具有通用性和灵活性,从而减少代码的冗余和维护的难度。

参数多态可以通过不同的方式实现,例如:

泛型:在静态类型语言(如 Java)中,可以使用泛型来实现参数多态。泛型允许我们在编译时确定数据类型,但是在运行时可以接受任意类型的参数。

动态类型:在动态类型语言(如 Python)中,可以在运行时动态的检查参数类型,从而实现参数多态。

基类和接口:在面向对象编程中,也可以通过使用基类和接口来实现参数多态。例如,我们可以定义一个抽象类,并让不同的子类实现这个抽象类,然后在函数中接受这个抽象类作为参数,从而实现参数多态。

3.子类型

多态子类型是指多态的一种特殊情况,即在继承关系中,一个子类可以当作其父类的一种类型使用。这种技术是面向对象编程的基础,可以使程序更加灵活,并减少代码的冗余。

例如,如果有一个父类Animal,它定义了一个吃的方法,那么我们可以创建一个子类Dog,并且它继承了Animal的吃的方法,同时也可以添加自己的特殊功能。我们可以将一个Dog对象当作Animal类型使用,这就是多态子类型。

多态子类型的优点:

  • 提高代码的可重用性:多态子类型可以在继承关系中重用父类的代码,从而提高代码的可重用性。

  • 减少代码的冗余:多态子类型可以减少代码的冗余,从而使代码更加简洁。

  • 提高程序的灵活性:多态子类型可以使程序更加灵活,并且可以在运行时动态地处理不同类型的对象。

2.2.2java中的多态

同一消息为不同的对象接受时可产生完全不同的行动,这种现象称为多态。

java中的多态其实是一种运行期的状态。为了实现运行期的多态,或者说动态绑定,需要满足三个条件:

  • 有类继承或者接口实现。
  • 子类要重写父类的方法。
  • 父类的引用指向子类的对象。

2.3 继承与实现

继承

继承是一种常见的代码复用方式,通过继承可以使得一个类从另一个类中继承属性和方法。

优点:增加系统的可重用性,减少重复。

继承使用extends关键字实现

实现

实现是另一种代码复用方式,它允许一个类实现一个接口,接口定义了一组方法,而类通过实现接口来获得这些方法。Java中的接口是抽象的,不能被实例化,但可以被实现。Java中的实现是多实现的,即一个类可以实现多个接口。

实现通过implements关键字。

2.4 多继承

1.多继承简介

对于一个类只有一个父类的情况,我们称之为单继承。而一个类同时有多个父类的情况叫做多继承。

在java中,一个类只能通过extends关键字继承另外一个类,不允许多继承。但是,在其他面向对象语言中是可能支持多继承的。eg:c++

在java8 之后就不是绝对的了。

2.菱形继承问题

假设我们有类B和类C,它们都继承了相同的类A。另外我们还有类D,类D通过多重继承机制继承了类B和类C。这时候,因为D同时继承了B和C,并且B和C又同时继承了A,那么,D中就会因为多重继承,继承到两份来自A中的属性和方法。

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

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

菱形继承是指多个类继承同一个类的情形,造成了继承关系的菱形形状。菱形继承问题是指由于多重继承导致的同一个方法在多个父类中的定义冲突的问题。

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

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

为了解决菱形继承问题,很多语言,包括Java语言,都采取了单继承的设计决策,从而避免了多重继承带来的问题。不过,Java语言通过接口的机制来提供多继承的效果,接口定义了一组方法,类可以通过实现接口来获得这些方法,因此Java语言支持多实现,不支持多继承。

2.5 组合与继承

1.面向对象的复用技术

面向对象编程提供了多种复用技术,以提高程序开发效率:

  1. 继承:通过继承,可以在已有类的基础上创建新类,并在新类中添加新的或覆盖原有的成员。

  2. 接口:接口是一组方法的声明,类可以通过实现接口来实现这些方法。接口可以提供多继承的效果。

  3. 多态:多态允许将一个子类对象当作其父类类型进行处理,从而实现代码复用。

  4. 抽象类:抽象类是一种特殊的类,可以被用作父类,但不能实例化。抽象类通常包含抽象方法,并在子类中被实现。

  5. 封装:封装是面向对象编程的重要概念,它允许将类的实现细节隐藏起来,从而避免了直接依赖细节的代码的破坏。

2.继承复用

is-a:表示"是一个"的关系,如狗是一个动物

3.组合

has-a:表示"有一个"的关系,如狗有一个尾巴

组合是面向对象编程中另一种复用技术,它比继承更加灵活,且不存在继承的限制。

组合的基本原理是,一个类可以通过成员变量的方式包含另一个类的实例。例如,在一个软件系统中,如果我们需要表示一个人有多个电话号码,我们可以定义一个名为Person的类,并在其中定义一个PhoneNumber类型的成员变量。这样,我们就可以创建Person类的实例,并在其中包含多个PhoneNumber实例。

组合可以在编写代码时赋予类更大的灵活性,并允许类具有更多不同类型的成员。同时,组合也使得代码更容易理解和维护,因为类与类之间的关系更加清晰明了。因此,组合是面向对象编程中的一种重要技术,广泛应用于软件系统的开发。

4.组合与继承的区别和联系

继承与组合是面向对象编程中两种重要的代码复用技术,有着不同的特点和用途。

继承是指一个类从另一个类继承其属性和行为,从而实现代码复用。继承关系表示一种父类和子类的类型关系,即子类继承父类的属性和行为,可以在不修改父类代码的情况下扩展父类的功能。继承关系在编写代码时具有一定的限制,例如,不能多继承。

组合是指一个类将另一个类作为其成员变量,从而实现代码复用。组合关系表示一种部分和整体的关系,即一个类作为另一个类的一部分。组合关系在编写代码时相对灵活,不存在继承的限制,例如,可以同时包含多个不同类型的对象。

总的来说,继承和组合都是为了实现代码复用,但是在使用时有着不同的限制和优缺点。开发人员在使用继承和组合时,需要根据实际需求和项目特点进行权衡和选择。

5.优缺点对比

组合关系 继承关系
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立 缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
优点:具体较好的可扩展性 缺点:支持扩展,但是往往以增加系统结构的复杂度为代价
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象 缺点:不支持动态继承。在运行时,子类无法选择不同父类
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口 缺点:子类不能改变父类的接口
缺点:整体类不能自动获得和局部类同样的接口 优点:子类能自动继承父类的接口
缺点:当创建整体类的对象时,需要创建所有局部类的对象 优点:当创建子类的对象时,无须创建父类的对象。

2.6 构造函数

构造函数是一种特殊的方法,用于创建一个类的实例并初始化对象的状态。在面向对象编程中,构造函数可以用来控制对象的创建方式和初始化状态。

在Java中,构造函数的名称与类名相同,并且不带返回类型。当创建一个类的新实例时,会自动调用相应的构造函数。例如:

class Example {
    
    
    int x;
    int y;

    public Example(int x, int y) {
    
    
        this.x = x;
        this.y = y;
    }
}

如果没有显式地定义构造函数,Java会自动生成一个默认的构造函数。构造函数可以重载,即同一个类可以有多个构造函数,根据不同的参数列表来进行重载。

2.7 变量

在Java中,变量是用来存储数据的容器,并可以在程序的运行期间被修改。

Java中的变量有以下特点:

  1. 每个变量在使用前必须先声明,并且声明时必须指定数据类型。

  2. 每个变量都有一个唯一的名称,用于在程序中引用该变量。

  3. 变量的数据类型决定了它能存储的数据类型。例如,一个int类型的变量只能存储整数值。

  4. 变量可以在程序的任意地方被修改,并且它的值可以在程序的任意地方被使用。

Java中有三种不同类型的变量:类变量、成员变量、局部变量。

类变量:也称为静态变量,是定义在类内部且使用static关键字声明的变量。类变量是该类的所有对象共享的,它们的值可以在类的任意地方被访问。

成员变量:是定义在类内部且没有使用static关键字声明的变量。成员变量是每个对象的私有的,它们的值可以在该对象的任意地方被访问。

局部变量:是定义在方法内部或构造函数内部的变量。局部变量的生存周期只在方法内部,它们的值只能在该方法内部被访问。

class Example {
    
    
  static int classVariable;
  int instanceVariable;

  public void method(int localVariable) {
    
    
    // statements using localVariable
  }
}

在这个例子中,类变量是classVariable,成员变量是instanceVariable,局部变量是localVariable。

2.8 成员变量和方法作用域

在 Java 中,成员变量和方法的作用域可以分为三种:public、private 和 protected。

public: 公共作用域,任何地方都可以访问该成员变量和方法。

private: 私有作用域,只有在当前类中才可以访问该成员变量和方法。

protected: 保护作用域,只有在当前类和子类中才可以访问该成员变量和方法。

默认情况下,成员变量和方法没有关键字修饰,作用域为包级可见。这意味着只有在相同包中的类才可以访问该成员变量和方法。

一般来说,通过使用 private 作用域,可以隐藏内部实现细节,并且保护对象的数据完整性。保护作用域则允许子类重写该方法。公共作用域用于暴露类的公共接口。

猜你喜欢

转载自blog.csdn.net/weixin_41317840/article/details/128864255
今日推荐