写在前面的话:这些是最基本最核心的思路,其他拓展不在此做延伸。一些知识点之后会持续进行整理改动,尽量做到简洁易懂且全面。此篇是我在其他平台写的笔记,排版细节没来得及更改。希望大家一起进步ヽ( ̄ω ̄( ̄ω ̄〃)ゝ
概述
面向对象设计(OOD)的核心编程思路可以概括为以下几个要点:
- 封装(Encapsulation):
-
- 将数据(属性)和方法(行为)封装在类内部,并通过访问控制修饰符限制外部对数据的访问。
- 抽象(Abstraction):
-
- 通过抽象类或接口定义必要的行为或特征,隐藏实现的细节,只暴露对外需要的功能。
- 继承(Inheritance):
-
- 通过继承使得一个类能够复用另一个类的功能,通过继承机制让一个类从另一个类派生,继承父类的属性和方法。
- 多态(Polymorphism):
-
- 通过方法重载(overloading)或方法重写(overriding)实现同一方法名在不同对象中的不同表现,从而提高代码的灵活性和扩展性。
- 依赖注入(Dependency Injection):
-
- 通过注入依赖对象来减少类之间的耦合,提升系统的可维护性和可测试性
封装、继承和多态的最核心步骤如下:
- 封装(Encapsulation):
-
- 定义类的属性和方法:将数据作为私有属性(
private
)定义,提供公共的访问方法(getter/setter)以控制对数据的访问。 - 限制外部访问:通过访问修饰符控制对类内部数据和方法的访问,保护数据不被直接修改。
- 定义类的属性和方法:将数据作为私有属性(
- 抽象(Abstraction)
-
- 使用抽象类或接口定义方法的签名(方法名、参数类型、返回类型),但不提供具体的实现。
- 具体的实现由子类提供,确保外部使用者只关心操作,而不需要关注实现的细节。
- 继承(Inheritance):
-
- 创建基类:定义一个基础类,包含共有的属性和方法。
- 派生子类:通过继承基类,子类可以复用或重写基类的方法和属性,实现代码复用和扩展。
- 多态(Polymorphism):
-
- 方法重载:在同一个类中,方法名相同,但参数列表不同。
- 方法重写:子类继承父类时,重写父类的方法以实现不同的功能。
- 对象的动态绑定:在运行时,程序决定调用哪个方法。多态通常依赖于父类引用指向子类对象的情况(如父类引用指向子类对象)。
每个特征的核心目标的总结:
- 封装(Encapsulation):保护数据的安全性,确保外部通过合法的方式访问和修改类的内部状态。
- 抽象(Abstraction):简化复杂系统的使用,隐藏实现细节,用户只关心操作,而不需关注具体实现。
- 继承(Inheritance):实现代码复用,子类可以扩展或修改父类功能,避免重复代码。
- 多态(Polymorphism):增强系统的灵活性和可扩展性,使得不同对象能够以相同接口展现不同的行为。
封装
在 Java 中,定义类的属性和方法通常包括以下几个关键步骤:
1. 定义属性(成员变量)
- 选择属性:根据类的功能,定义该类的属性。属性通常用来保存对象的状态。
- 设定访问控制:Java 提供了 4 种访问控制符:
-
private
:私有,只有类内部可以访问。default
(包私有):在同一包内可访问。protected
:子类或同一包中的其他类可以访问。public
:任何类都可以访问。
- 初始化属性:可以通过构造方法初始化属性,也可以使用直接初始化的方式。
2. 定义方法(成员函数)
- 选择方法:根据类的功能,定义可以操作属性、执行任务或者提供服务的方法。
- 设定访问控制:类似属性方法也需要设定访问修饰符来控制访问权限。
- 返回类型:每个方法必须指定返回类型,若没有返回值,则为
void
。 - 方法签名:包括方法名称、参数和返回值类型。
- 实现功能:在方法体内定义方法的具体实现。
示例:一个简单的 Car
类
javaCopy Codepublic class Car {
// 定义属性
private String brand; // 品牌
private String model; // 型号
private int year; // 年份
// 构造方法,初始化属性
public Car(String brand, String model, int year) {
this.brand = brand;
this.model = model;
this.year = year;
}
// 定义访问方法(getter)
public String getBrand() {
return this.brand;
}
public String getModel() {
return this.model;
}
public int getYear() {
return this.year;
}
// 定义行为方法(如启动引擎)
public void startEngine() {
System.out.println("The " + this.brand + " " + this.model + " is starting.");
}
// 定义行为方法(修改属性)
public void setYear(int year) {
this.year = year;
}
}
解释
- 属性定义:
-
private String brand;
:定义了一个私有属性brand
,用于存储品牌信息。private String model;
:定义了一个私有属性model
,用于存储车型信息。private int year;
:定义了一个私有属性year
,用于存储汽车年份。
- 构造方法:
-
public Car(String brand, String model, int year)
:这是一个构造方法,用来初始化类的属性。构造方法的名字与类名相同。
- 访问方法(getter):
-
public String getBrand()
:这是一个公共方法,用来获取brand
属性的值。public String getModel()
:用于获取model
属性的值。public int getYear()
:用于获取year
属性的值。
- 行为方法:
-
public void startEngine()
:这是一个公共方法,用于输出汽车启动的消息。public void setYear(int year)
:这是一个公共方法,用来修改year
属性的值。
总结
- 属性:在类中定义变量,用于存储对象的状态,通常设为私有(
private
)以保护数据。 - 方法:定义类的行为,可以操作属性,完成任务或提供服务。方法的访问控制和返回类型需要根据需求进行设定。
这种结构帮助把数据(属性)和行为(方法)结合在一起,增强代码的封装性、可维护性和扩展性。
继承
1. 创建基类(父类)
基类是一个包含共有属性和方法的类,通常定义那些对所有子类都通用的功能。
示例:创建一个基类 Animal
javaCopy Codepublic class Animal {
// 基类属性
protected String name;
protected int age;
// 构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
// 基类方法
public void eat() {
System.out.println(name + " is eating.");
}
public void sleep() {
System.out.println(name + " is sleeping.");
}
}
- 属性:
name
和age
是基类中的成员变量,表示动物的名字和年龄。 - 构造方法:
Animal(String name, int age)
用来初始化基类对象的属性。 - 方法:
eat()
和sleep()
是基类的方法,所有继承Animal
的子类都会拥有这些方法。
2. 创建派生类(子类)
派生类继承基类的属性和方法,并可以根据需要重写(override)基类的方法,或者添加新的属性和方法。派生类使用 extends
关键字来继承基类。
示例:创建一个派生类 Dog
,继承 Animal
javaCopy Codepublic class Dog extends Animal {
// 子类特有的属性
private String breed;
// 构造方法
public Dog(String name, int age, String breed) {
super(name, age); // 调用父类的构造方法
this.breed = breed;
}
// 重写父类方法
@Override
public void eat() {
System.out.println(name + " the dog is eating.");
}
// 子类特有的方法
public void bark() {
System.out.println(name + " is barking.");
}
}
- 继承:
Dog
使用extends Animal
关键字继承了Animal
类。 - 构造方法:在子类的构造方法中,使用
super(name, age)
调用了父类的构造方法,以初始化继承自父类的属性。 - 方法重写:子类
Dog
重写了父类Animal
的eat()
方法,提供了不同的实现。 - 新增方法:
bark()
是Dog
类特有的方法,它不是父类的一部分。
3. 使用继承的示例
继承可以使得子类对象拥有父类的属性和方法,并且可以调用子类新增的方法或重写的方法。
javaCopy Codepublic class Main {
public static void main(String[] args) {
// 创建一个 Dog 对象
Dog dog = new Dog("Buddy", 3, "Golden Retriever");
// 调用继承自 Animal 的方法
dog.eat(); // 调用 Dog 类中重写的 eat() 方法
dog.sleep(); // 调用继承自 Animal 的 sleep() 方法
// 调用 Dog 类特有的方法
dog.bark();
}
}
输出:
Copy CodeBuddy the dog is eating.
Buddy is sleeping.
Buddy is barking.
4. 继承中的关键点
super
关键字:用于在子类中调用父类的构造方法、属性和方法。
-
super()
调用父类的构造方法。super.property
或super.method()
用于访问父类的属性或方法。
- 方法重写(Overriding):子类可以通过
@Override
注解重写父类的方法。重写的方法可以提供与父类方法不同的实现。
-
- 方法签名必须一致:方法名、参数类型、返回类型相同。
protected
和private
成员:
-
- 子类可以访问父类的
public
和protected
成员,但不能访问private
成员。 private
成员只在父类的内部可见。
- 子类可以访问父类的
- 多层继承:
-
- Java 支持单继承,即一个类只能继承一个父类。但一个类可以继承多层父类(父类继承父类,形成继承链)。
5. 多态(Polymorphism)
继承与多态密切相关,派生类对象可以在父类引用中使用,体现了多态性。即父类引用可以指向子类对象,并且根据实际对象调用方法时会执行子类的实现。
javaCopy Codepublic class Main {
public static void main(String[] args) {
Animal myDog = new Dog("Buddy", 3, "Golden Retriever");
myDog.eat(); // 调用的是 Dog 类中的 eat 方法
}
}
输出:
Copy CodeBuddy the dog is eating.
总结
在 Java 中,创建基类和派生类的步骤包括:
- 创建基类,定义公共属性和方法。
- 创建派生类,使用
extends
关键字继承基类。 - 在子类中重写父类的方法,或者新增特有的属性和方法。
- 使用
super
调用父类的构造方法和成员。
多态
在 Java 中,多态是面向对象编程中的一个核心概念,它允许通过父类的引用来操作不同子类的对象。而多态的实现通常与方法重载和方法重写相关。这两者有着不同的含义和使用方式,下面详细介绍它们:
1. 方法重载(Method Overloading)
方法重载指的是在同一个类中定义多个方法,它们具有相同的名称但参数列表不同(参数的个数、类型或顺序不同)。方法重载与返回类型无关,Java 编译器会根据方法的参数类型来区分重载的方法。
主要特征
- 方法名相同。
- 参数不同(类型、个数、顺序)。
- 返回类型可以相同,也可以不同,但返回类型不作为区分的方法重载的标准。
- 方法重载是在编译时进行决定的,所以属于静态多态。
示例:方法重载
javaCopy Codepublic class Calculator {
// 重载加法方法(两个整数相加)
public int add(int a, int b) {
return a + b;
}
// 重载加法方法(两个浮动数相加)
public double add(double a, double b) {
return a + b;
}
// 重载加法方法(三个整数相加)
public int add(int a, int b, int c) {
return a + b + c;
}
}
使用方法重载
javaCopy Codepublic class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // 调用两个整数相加的方法
System.out.println(calc.add(2.5, 3.5)); // 调用两个浮动数相加的方法
System.out.println(calc.add(1, 2, 3)); // 调用三个整数相加的方法
}
}
输出:
Copy Code5
6.0
6
2. 方法重写(Method Overriding)
方法重写是子类重新定义父类的方法。重写的方法具有相同的方法名、相同的参数列表和相同的返回类型。方法重写是在运行时进行的,因此属于动态多态。它使得子类可以根据自己的需要改变父类方法的实现。
主要特征
- 方法名相同。
- 参数列表相同。
- 返回类型相同(或是父类返回类型的子类型,即协变返回类型)。
- 访问权限不能比父类的方法更严格,通常访问权限是“从父类继承的方法访问权限最宽松”。
- 只在继承和实现接口的情况下才会发生方法重写。
- 方法重写是动态绑定,即通过对象的实际类型来决定调用哪个方法。
示例:方法重写
javaCopy Codeclass Animal {
// 父类方法
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
// 子类重写父类的方法
@Override
public void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
// 子类重写父类的方法
@Override
public void sound() {
System.out.println("Cat meows");
}
}
使用方法重写
javaCopy Codepublic class Main {
public static void main(String[] args) {
Animal animal1 = new Dog(); // Animal 引用指向 Dog 对象
Animal animal2 = new Cat(); // Animal 引用指向 Cat 对象
animal1.sound(); // 调用 Dog 类中的 sound 方法
animal2.sound(); // 调用 Cat 类中的 sound 方法
}
}
输出:
Copy CodeDog barks
Cat meows
方法重载与方法重写的区别总结
特性 | 方法重载 (Overloading) | 方法重写 (Overriding) |
方法名 | 相同 | 相同 |
参数列表 | 参数类型、数量、顺序不同 | 参数列表相同 |
返回类型 | 可以相同,也可以不同(不依赖于返回类型) | 返回类型必须相同,或者是父类返回类型的子类型(协变) |
发生时机 | 编译时(静态多态) | 运行时(动态多态) |
访问修饰符 | 可以不同,但不能比父类方法的访问权限更严格 | 不能比父类方法的访问权限更严格(可以相同或更宽松) |
实现方式 | 同一类中通过改变方法参数列表来实现 | 子类通过重写父类的方法实现 |
是否继承相关 | 不涉及继承 | 必须在继承关系或实现接口的情况下发生 |
总结
- 方法重载(Overloading)是指同一个类中可以定义多个相同方法名、不同参数列表的方法,编译时根据调用时的参数来决定调用哪个方法。
- 方法重写(Overriding)是指子类可以重新定义父类中已经存在的方法,方法名和参数列表必须相同,运行时根据对象的实际类型来决定调用哪个方法。
两者都在 Java 中实现了多态机制,但方法重载是静态多态,方法重写是动态多态。