note
多态与继承
一、继承(Inheritance)
1. 基础概念
定义:一个类(子类 / 派生类)可以复用、扩展另一个类(父类 / 基类)的属性和方法,实现代码复用。
核心作用:减少重复代码,建立类之间的层级关系。
2. 代码中的体现
- 子类继承父类
子类自动拥有父类所有非私有的属性和方法。
父类是通用模板,子类是具体实现。
- 方法重写(Override)
子类可以定义和父类同名、同参数的方法,覆盖父类的实现。
重写是多态的前提。
- 调用父类方法
使用
super()
调用父类的方法,常用于:
初始化父类属性
保留父类逻辑 + 扩展子类逻辑
3. 继承的特点
- 单继承:一个子类只能直接继承一个父类。
- 传递性:A → B → C,C 可以使用 A 的属性和方法。
- is-a 关系:子类
is a父类(例如:猫 is a 动物)。
二、多态(Polymorphism)
1. 基础概念
定义:同一个方法名,在不同子类中表现出不同的行为。
核心前提:必须先有继承 + 方法重写。
核心思想:接口统一,实现不同。
2. 多态的 3 个必要条件
- 存在继承关系
- 子类重写父类方法
- 父类引用指向子类对象(使用父类类型接收子类实例)
调用时只看对象类型,不看引用类型。
同一个方法名,不同子类执行不同逻辑。
4. 多态的优势
开闭原则:新增子类无需修改原有代码。
统一调用:不管子类多少,调用方式完全一致。
扩展性极强:方便新增功能、维护系统。
三、继承 + 多态 完整执行流程
- 定义父类:提供通用方法(可抽象、可具体)。
- 定义子类:继承父类,重写方法。
- 创建子类对象,用父类类型接收。
- 调用同名方法:自动执行对应子类的实现 → 多态效果。
四、关键区别总结
表格
| 特性 | 继承 | 多态 |
|---|---|---|
| 目的 | 代码复用、扩展 | 统一接口、不同实现 |
| 关系 | 类与类的层级关系 | 方法的行为表现 |
| 前提 | 无 | 必须有继承 + 重写 |
| 关键字 | 类名 (父类) | 父类引用指向子类对象 |
五、最佳实践
- 父类做规范:定义通用方法,让子类必须实现。
- 子类做实现:重写方法,实现自身业务逻辑。
- 多用父类类型传参 / 接收:让程序自动适配所有子类。
- 少用多重继承:避免逻辑混乱。
总结
- 继承 = 代码复用 + 层级关系,核心是
extends/类(父类)+super()。 - 多态 = 统一接口,不同实现,依赖继承 + 方法重写 + 父类引用指向子类对象。
- 两者配合:让代码复用性、扩展性、可维护性大幅提升,是面向对象的核心设计思想。
代码
Main.java
// 导入ArrayList和Scanner
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
// 静态集合:存放所有注册的用户对象
static ArrayList<User> userList = new ArrayList<>();//动态增删元素的容器
// 静态集合:存放所有新闻对象
static ArrayList<News> newsList = new ArrayList<>();
// 当前登录的用户对象,未登录时为null
static User currentUser = null;
// 扫描器,用于接收键盘输入
static Scanner scanner = new Scanner(System.in);
//程序入口
public static void main(String[] args) {
while (true) {// 无限循环,一直显示主菜单除非用户主动退出
System.out.println("\n====== 微头条主菜单 ======");
System.out.println("1. 注册");
System.out.println("2. 登录");
System.out.println("3. 查看新闻列表");
System.out.println("4. 发布新闻");
System.out.println("5. 退出");
System.out.print("请选择:");
int choice = scanner.nextInt();//输入整数,创建scanner同时导入包
scanner.nextLine(); // 吃掉换行符,否则会读到空字符,跳过输入
switch (choice) {
case 1:
register(); // 调用注册方法
break;//回到while
case 2:
login(); // 调用登录方法
break;
case 3:
showNewsList(); // 显示新闻列表
break;
case 4:
publishNews(); // 发布新闻
break;
case 5:
System.out.println("再见!");
scanner.close();
return; // 结束main方法,程序退出
default:
System.out.println("无效选择!");
}
}
}
// 注册方法
static void register() {
System.out.print("用户名:");
String name = scanner.nextLine();
// 检查用户名是否存在
for (User u : userList) {
if (u.getUsername().equals(name)) {
System.out.println("用户名已存在!");
return;
}
}
System.out.print("密码:");
String pwd = scanner.nextLine();
System.out.print("请选择角色(1.普通用户 2.管理员):");
int role = scanner.nextInt();
scanner.nextLine();
User user;
if (role == 2) {
user = new Admin(name, pwd); // 创建管理员对象
} else {
user = new User(name, pwd); // 创建普通用户对象
}
userList.add(user);
System.out.println("注册成功!");
}
// 登录方法
static void login() {
System.out.print("用户名:");
String name = scanner.nextLine();
System.out.print("密码:");
String pwd = scanner.nextLine();
// 遍历userList,查找匹配的用户名和密码
for (User u : userList) {
if (u.getUsername().equals(name) && u.getPassword().equals(pwd)) {
currentUser = u; // 记录当前登录的用户对象
//【新增】根据用户类型显示不同的登录成功提示
if (currentUser instanceof Admin) {
System.out.println("管理员登录成功!");
} else {
System.out.println("普通用户登录成功!");
}
//【新增】进入用户菜单循环(多态展示的舞台)
while (true) {
//【新增】多态调用:自动执行子类重写的菜单方法
currentUser.showMenu();
//【新增】接收用户的菜单选择
System.out.print("请输入您的选择:");
int choice = scanner.nextInt();
scanner.nextLine();//【新增】吸收多余的换行符,防止输入错位
//【新增】退出选项(假设输入 0 是退出登录)
if (choice == 0) {
currentUser = null;//【新增】清空当前用户状态
System.out.println("已退出登录\n");
return; //【新增】直接结束 login 方法,回到主界面
}
//【新增】使用 switch 处理其他业务逻辑
switch (choice) {
case 1: publishNews(); break;
case 2: showNewsList(); break;
case 3: showNewsDetail(); break;
case 4:
//【新增】向下转型判断:判断是否有删除权限
if (currentUser instanceof Admin) {
deleteNews();
} else {
System.out.println("您没有权限执行此操作!\n");
}
break;
default: System.out.println("无效选择\n"); //【新增】处理非法输入
}
}
}
}
// 未找到匹配的用户
System.out.println("用户名或密码错误!\n");
}
// 发布新闻方法
static void publishNews() {
// 检查是否已登录
if (currentUser == null) {
System.out.println("请先登录!");
return;
}
System.out.print("标题:");
String title = scanner.nextLine();
System.out.print("内容:");
String content = scanner.nextLine();
// 创建News对象,自动生成发布时间,并添加到newsList集合中
newsList.add(new News(title, content));
System.out.println("发布成功!");
}
// 查看新闻列表方法
static void showNewsList() {
System.out.println("\n====== 新闻列表 ======");
// 遍历newsList,按顺序显示每条新闻的标题和发布时间
for (int i = 0; i < newsList.size(); i++) {
News n = newsList.get(i);
// 编号从1开始,所以用(i+1)
System.out.println((i+1) + ". " + n.getTitle() + " (" + n.getPublishTime() + ")");
}
}
// 查看新闻详情方法
static void showNewsDetail() {
if (newsList.isEmpty()) {
System.out.println("暂无新闻!");
return;
}
System.out.print("请输入要查看的新闻编号:");
int num = scanner.nextInt();
scanner.nextLine();
if (num < 1 || num > newsList.size()) {
System.out.println("无效的新闻编号!");
return;
}
News n = newsList.get(num - 1);
System.out.println("\n====== 新闻详情 ======");
System.out.println("标题:" + n.getTitle());
System.out.println("内容:" + n.getContent());
System.out.println("发布时间:" + n.getPublishTime());
System.out.println("=====================\n");
}
// 删除新闻方法
static void deleteNews() {
if (newsList.isEmpty()) {
System.out.println("暂无新闻可删除!");
return;
}
System.out.print("请输入要删除的新闻编号:");
int num = scanner.nextInt();
scanner.nextLine();
if (num < 1 || num > newsList.size()) {
System.out.println("无效的新闻编号!");
return;
}
News removed = newsList.remove(num - 1);
System.out.println("已删除新闻:" + removed.getTitle());
}
}
Admin.java
public class Admin extends User {
public Admin(String username, String password) {
super(username, password); // 调用父类构造器,初始化用户名和密码
}
@Override
public void showMenu() {
System.out.println("\n===== 管理员菜单 =====");
System.out.println("1. 发布新闻");
System.out.println("2. 查看新闻列表");
System.out.println("3. 查看新闻详情");
System.out.println("4. 删除任意新闻"); // 管理员特有选项
System.out.println("5. 退出登录");
}
}
News.java
import java.text.SimpleDateFormat; // 导入日期格式化工具类,用于将日期转换为指定格式的字符串
import java.util.Date; // 导入Date日期类,用于获取当前系统时间
public class News { // 定义一个公开的News类(新闻类),用于封装新闻信息
private String title; // 私有属性:新闻标题,只能在当前类内部访问
private String content; // 私有属性:新闻内容,只能在当前类内部访问
private String publishTime; // 私有属性:发布时间(字符串类型),存储格式化后的时间
// 有参构造方法,创建新闻对象必须传入标题和内容
public News(String title, String content) {
this.title = title; // 将参数title赋值给当前对象的title属性
this.content = content;// 将参数content赋值给当前对象的content属性
// 获取当前系统时间,格式化为"年-月-日 时:分:秒"后存入publishTime
this.publishTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
// getter方法:获取新闻标题
public String getTitle() {
return title; // 返回当前对象的title属性值
}
// getter方法:获取新闻内容
public String getContent() {
return content; // 返回当前对象的content属性值
}
// getter方法:获取发布时间
public String getPublishTime() {
return publishTime; // 返回当前对象的publishTime属性值
}
}
User.java
public class User {
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
// 普通用户的菜单
public void showMenu() {
System.out.println("\n===== 普通用户菜单 =====");
System.out.println("1. 发布新闻");
System.out.println("2. 查看新闻列表");
System.out.println("3. 查看新闻详情");
System.out.println("4. 退出登录");
}
}
浙公网安备 33010602011771号