单聊和群聊
TCP协议单聊
服务端:
import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class fuwuchuangkou extends JFrame {
private JTextArea ta_info;
private ServerSocket server; // 声明ServerSocket对象
private Socket socket; // 声明Socket对象socket
private Vector<Socket> vector = new Vector<Socket>();// 用于存储连接到服务器的客户端套接字对象
public void createSocket() {
try {
server = new ServerSocket(1978);
while (true) {
ta_info.append("等待新客户连接......\n");
socket = server.accept();// 创建套接字对象
vector.add(socket);// 将套接字对象添加到向量对象中
ta_info.append("客户端连接成功。" + socket + "\n");
new ServerThread(socket).start();// 创建并启动线程对象
}
} catch (IOException e) {
e.printStackTrace();
}
}
class ServerThread extends Thread {
Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));// 创建输入流对象
while (true) {
String info = in.readLine();// 读取信息
for (Socket s : vector) {// 遍历所有客户端套接字对象
if (s != socket) {// 如果不是发送信息的套接字对象
PrintWriter out = new PrintWriter(s
.getOutputStream(), true);// 创建输出流对象
out.println(info);// 发送信息
out.flush();// 刷新输出缓冲区
}
}
}
} catch (IOException e) {
ta_info.append(socket + "已经退出。\n");
vector.remove(socket);// 移除退出的客户端套接字
}
}
}
public static void main(String args[]) {
fuwuchuangkou frame = new fuwuchuangkou();
frame.setVisible(true);
frame.createSocket();
}
/**
* Create the frame
*/
public fuwuchuangkou() {
super();
setTitle("一对一");
setBounds(100, 100, 385, 266);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
ta_info = new JTextArea();
scrollPane.setViewportView(ta_info);
}
}
客户端:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class kehuchuangkou extends JFrame {
private JTextArea ta_info;
private JTextField tf_send;
PrintWriter out;// 声明输出流对象
/**
* Launch the application
*
* @param args
*/
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
kehuchuangkou frame = new kehuchuangkou();
frame.setVisible(true);
frame.createClientSocket();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void createClientSocket() {
try {
Socket socket = new Socket("127.0.0.1", 1978);// 连接本地1978端口
out = new PrintWriter(socket.getOutputStream(), true);// 创建输出流对象
new ClientThread(socket).start();// 创建并启动线程对象
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class ClientThread extends Thread {
Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));// 创建输入流对象
while (true) {
String info = in.readLine();// 读取信息
ta_info.append(info + "\n");// 在文本域中显示信息
if (info.equals("88")) {
break;// 结束线程
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void send() {
String info = tf_send.getText();// 获得输入的信息
if (info.equals("")) {
return;// 如果没输入信息则返回,即不发送
}
if (info.equals("88")) {
System.exit(0);// 如果没输入信息是88,则退出
}
out.println(info);// 发送信息
out.flush();// 刷新输出缓冲区
tf_send.setText(null);// 清空文本框
}
public kehuchuangkou() { //创建面板
super();
setTitle("一对一");
setBounds(100, 100, 385, 266);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
getContentPane().add(panel, BorderLayout.SOUTH);
final JLabel label = new JLabel();
label.setText("输入聊天内容:");
panel.add(label);
tf_send = new JTextField();
tf_send.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
send();
}
});
tf_send.setPreferredSize(new Dimension(180, 25));
panel.add(tf_send);
final JButton button = new JButton();
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
send();
}
});
button.setText("发 送");
panel.add(button);
final JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
ta_info = new JTextArea();
scrollPane.setViewportView(ta_info);
}
}
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class kehu1 extends JFrame {
private JTextArea ta_info;
private JTextField tf_send;
PrintWriter out;// 声明输出流对象
/**
* Launch the application
*
* @param args
*/
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
kehuchuangkou frame = new kehuchuangkou();
frame.setVisible(true);
frame.createClientSocket();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public void createClientSocket() {
try {
Socket socket = new Socket("127.0.0.1", 1978);// 连接本地1978端口
out = new PrintWriter(socket.getOutputStream(), true);// 创建输出流对象
new ClientThread(socket).start();// 创建并启动线程对象
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
class ClientThread extends Thread {
Socket socket;
public ClientThread(Socket socket) {
this.socket = socket;
}
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));// 创建输入流对象
while (true) {
String info = in.readLine();// 读取信息
ta_info.append(info + "\n");// 在文本域中显示信息
if (info.equals("88")) {
break;// 结束线程
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void send() {
String info = tf_send.getText();// 获得输入的信息
if (info.equals("")) {
return;// 如果没输入信息则返回,即不发送
}
if (info.equals("88")) {
System.exit(0);// 如果没输入信息是88,则退出
}
out.println(info);// 发送信息
out.flush();// 刷新输出缓冲区
tf_send.setText(null);// 清空文本框
}
public kehu1() { //创建面板
super();
setTitle("一对一");
setBounds(100, 100, 385, 266);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
getContentPane().add(panel, BorderLayout.SOUTH);
final JLabel label = new JLabel();
label.setText("输入聊天内容:");
panel.add(label);
tf_send = new JTextField();
tf_send.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
send();
}
});
tf_send.setPreferredSize(new Dimension(180, 25));
panel.add(tf_send);
final JButton button = new JButton();
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
send();
}
});
button.setText("发 送");
panel.add(button);
final JScrollPane scrollPane = new JScrollPane();
getContentPane().add(scrollPane, BorderLayout.CENTER);
ta_info = new JTextArea();
scrollPane.setViewportView(ta_info);
}
}
结果
UDP协议群聊
服务端:
import java.io.*;
import java.net.*;
import java.util.ArrayList;
public class Server{
public static ServerSocket server_socket;
public static ArrayList<Socket> socketList=new ArrayList<Socket>();
public static void main(String []args){
try{
server_socket = new ServerSocket(5000);
while(true){
Socket socket = server_socket.accept();
socketList.add(socket); //把sock对象加入sock集合
ServerBO_Thread st=new ServerBO_Thread(socket,socketList); //初始化多线程
st.start();//启动多线程
}
}catch(Exception ex){
ex.printStackTrace();
}finally{
try{
if(server_socket!=null){
server_socket.close();
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
public void encryptWrite(String src,DataOutputStream output)throws IOException{
//将一个字符串转化为字符数组
//System.out.println(src);
char[] char_arr = src.toCharArray();
//加密操作
for(int i = 0;i<char_arr.length;i++){
output.writeChar(char_arr[i]+13);
}
//用作结束标志符
output.writeChar(2333);
output.flush();
}
//读取并解密
public String readDecrypt(DataInputStream input)throws IOException{
String rtn="";
while(true){
int char_src =input.readChar();
if(char_src!=2333){
rtn=rtn+(char)(char_src-13);
}else{
break;
}
}
return rtn;
}
}
class ServerBO_Thread extends Thread{
Socket client = null;
ArrayList<Socket> clients;
ServerBO_Thread(Socket s,ArrayList<Socket> ss){//初始化
client=s;
clients=ss;
}
public void run(){
DataInputStream input = null;
DataOutputStream output =null;
try{
input = new DataInputStream(client.getInputStream());
Server bo = new Server();
String receive=null;
String send=null;
while(true){//监视当前客户端有没有发来消息
if(!client.isClosed()){
receive=bo.readDecrypt(input);
clients.trimToSize();
String[] param = receive.split("&");
if(")start".equals(param[1])){ //分析客户端发来的内容
send = param[0]+"进入聊天室";
}else{
send = param[0]+"说: "+param[1];
}
if(!("3333".equals(param[1]))){//3333为退出聊天室信号
for(Socket socket:clients){ //遍历socke集合
//把读取到的消息发送给各个客户端
if(!socket.isClosed()){
output = new DataOutputStream(socket.getOutputStream());
bo.encryptWrite(send,output);
}
}
}else{//如果有客户端退出
for(Socket socket:clients){ //遍历socke集合
if(socket!=client){//告诉其他人此人退出聊天室
if(!(socket.isClosed())){
output = new DataOutputStream(socket.getOutputStream());
bo.encryptWrite(param[0]+"已退出聊天室",output);
}
}
}
output = new DataOutputStream(client.getOutputStream());
bo.encryptWrite("3333",output);//返回信号给要退出的客户端,然后关闭线程
client.close();
input.close();
output.close();
}
}else{
break;
}
}
}catch(Exception ex){
ex.printStackTrace();
}
}
}
客户端:
import java.io.IOException;
import java.util.Scanner;
import java.net.*;
import java.io.*;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.DataOutputStream;
public class People{
//服务端ip
public String ip = "127.0.0.1";
//服务端端口
public int port = 5000;
public DataOutputStream output = null;
public Socket socket = null;
public DataInputStream input = null;
public Scanner sc =new Scanner (System.in);
public String send ;
public String receive;
public String name;
public String sd = null;
public static void main(String[]aa){
People po = new People();
po.start();
}
public void start(){
try{
System.out.println("*******欢迎使用匿名聊天室!**********");
System.out.println("请输入你将要使用的昵称:");
name=sc.nextLine();//获取昵称
socket = new Socket(ip,port);
output=new DataOutputStream(socket.getOutputStream());
input = new DataInputStream(socket.getInputStream());
send = name+"&)start";//把昵称发送到server 告诉所有人有新成员加入聊天室
System.out.println("(如果要退出聊天室请输入“3333”!)");
System.out.println("*******成功进入匿名聊天室!**********");
System.out.println("");
encryptWrite(send,output);
Out out=new Out(output,name,input,socket);
out.start();//启动发送聊天内容的多线程
while(true){
String receive = readDecrypt(input);
if("3333".equals(receive)){//如果收到“3333”则退出聊天室
System.out.println("*******成功退出匿名聊天室!**********");
input.close();
output.close();
socket.close();
System.exit(0);
}
System.out.println(receive);
}
}catch(Exception ex){
ex.printStackTrace();
}finally{
try{
if(socket!=null) socket.close();
input.close();
output.close();
}catch(Exception ex){
ex.printStackTrace();
}
}
}
public void encryptWrite(String src,DataOutputStream output)throws IOException{
//将一个字符串转化为字符数组
char[] char_arr = src.toCharArray();
//加密操作
for(int i = 0;i<char_arr.length;i++){
output.writeChar(char_arr[i]+13);
}
//用作结束标志符
output.writeChar(2333);
output.flush();
}
//读取并解密
public String readDecrypt(DataInputStream input)throws IOException{
String rtn="";
while(true){
int char_src =input.readChar();
if(char_src!=2333){
rtn=rtn+(char)(char_src-13);
}else{
break;
}
}
return rtn;
}
}
class Out extends Thread {
public DataOutputStream output;
public DataInputStream input;
public static String name;
public Socket socket;
public Scanner sc =new Scanner (System.in);
Out(DataOutputStream ot,String n,DataInputStream it,Socket socket){
output=ot;
input=it;
name=n;
}
public void run(){
People po = new People();
try{
while(true){
String send=sc.nextLine();//获取用户输入
String send2=name+"&"+send;//把聊天内容打包成约定形式
po.encryptWrite(send2,output);
}
}catch(Exception ex){
ex.printStackTrace();
}finally{
System.out.println("sfef");
}
}
}
结果:
相关文章:

单聊和群聊
TCP协议单聊 服务端: import java.awt.BorderLayout; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Vec…...
Swift 检测 iCloud状态
Show me the code: func isICloudContainerAvailable() -> Bool {if let _ FileManager.default.ubiquityIdentityToken {return true} else {return false} }推荐一下刚上线的 App 熊猫小账本,里面有用到这篇博客讲的内容 熊猫小账本 一个简洁的记账 App&…...
使用Windi CSS(基于vue-cli)
1、先创建vue项目 利用脚手架vue-cli创建,根据需求设置vue版本、babel等,无特别要求直接用默认的vue2或vue3就行 vue create 项目名 2、运行vue项目,利用vue-cli安装Windi CSS 官网指导:Vue CLI 集成 | Windi CSS 我的经历&a…...

操作无法完成(错误 0x000006ba),Windows 11 PDF打印机无法使用解决办法
操作无法完成(错误 0x000006ba),Windows 11 PDF打印机无法使用解决办法 解决方式一 先重启一次电脑,看看是否可以解决问题。 解决方式二 重新启动 Printer Spooler 服务...

Settings中电池选项-Android13
Settings中电池选项-Android13 1、设置中界面2、电池计算2.1 充电时间计算2.1.1 BatteryUsageStats获取2.1.2 BatteryStatsImpl计算 2.2 电池剩余使用时间2.2.1 Estimate获取2.2.2 BatteryStatsImpl计算 3、电池信息来源4、命令模拟* 日志 [电池]Android 9.0 电池未充电与充电字…...
解密 Java ForEach 提前终止问题
目录 前言:场景复现分析与解决方案解决方案详解总结 前言: 你是否曾在使用 Java 8 的 forEach 迭代集合时遇到过提前终止循环的问题?在这篇博客中,我们将深入探讨这一问题,并提供多种解决方案。通过场景复现、分析源码…...

7_js_dom编程入门1
Objective(本课目标) 掌握获取页面元素的常用方法 掌握事件触发案例 能够区分innerText和innerHTML的区别 综合案例训练 1 DOM 介绍 1.1 什么是DOM 文档对象模型(Document Object Model,简称DOM),是 …...

使用 Elasticsearch 检测抄袭 (一)
作者:Priscilla Parodi 抄袭可以是直接的,涉及复制部分或全部内容,也可以是释义的,即通过更改一些单词或短语来重新表述作者的作品。 灵感和释义之间是有区别的。 即使你得出类似的结论,也可以阅读内容,获得…...

STM32 cubeMX 直流电机控制风扇转动
本文使用的是 HAL 库。 文章目录 前言一、直流电机介绍二、直流电机原理图三、直流电机控制方法四、STM32CubeMX 配置直流电机五、代码编写总结 前言 实验开发板:STM32F051K8。所需软件:keil5 , cubeMX 。实验目的:了解 直流电机…...

我在 VSCode 插件里接入了 ChatGPT,解决了Bug无法定位的难题
作为一名软件开发者,我时常面临着代码中Bug的定位和解决问题。这个过程往往既费时又充满挑战。然而,最近我在我的VSCode插件中接入了ChatGPT,这个决定彻底改变了我处理Bug的方式。 Bug:开发者的噩梦 在开发过程中,遇…...
学Java的第四天
一、switch语句 switch (表达式) { case 1: 语句体1; break; case 2: 语句体2; break; ... default: 语句体n1; break; } 首先计算表达式的值,然后和case 比较,有对应的值就执行对应的语句,遇到 break 就结束。 最后如果所有的cas…...

[内功修炼]函数栈帧的创建与销毁
文章目录 1:什么是函数栈帧2:理解函数栈帧能解决什么问题呢3:函数栈帧的创建与销毁的解析3.1:什么是栈3.2:认识相关寄存器与汇编指令相关寄存器相关汇编指令 3.3 解析函数栈帧的创建和销毁3.3.1 预备知识3.3.2 详细解析一:调用main函数,为main函数开辟函数栈帧First:push前push…...

【深度学习-目标检测】03 - Faster R-CNN 论文学习与总结
论文地址:Faster R-CNN: Towards Real-Time ObjectDetection with Region Proposal Networks 论文学习 1. 摘要与引言 研究背景与挑战:当前最先进的目标检测网络依赖于 区域提议(Region Proposals)来假设目标的位置,…...
oracle11体系结构二-存储结构
数据区: 数据区(数据扩展区)由一组连续的oracle数据块所构成的存储结构,一个或多个数据块组成一个数据区,一个或多个数据区组成一个段。当段中所有空间被使用完后,oracle系统将自动为该段分配一个新的数据…...

如何通过内网穿透实现远程访问本地Linux SVN服务
文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…...

网页乱码问题(edge浏览器)
网页乱码问题(edge) 文章目录 网页乱码问题(edge)前言一、网页乱码问题1.是什么:(描述)2.解决方法:(针对edge浏览器)(1)下载charset插…...

泛微OA xmlrpcServlet接口任意文件读取漏洞(CNVD-2022-43245)
CNVD-2022-43245 泛微e-cology XmlRpcServlet接口处存在任意文件读取漏洞,攻击者可利用漏洞获取敏感信息。 1.漏洞级别 中危 2.影响范围 e-office < 9.5 202201133.漏洞搜索 fofa 搜索 app"泛微-OA(e-cology)"4.漏洞复现 …...

MATLAB ga函数的使用方法
一、ga句法结构 x ga(fitnessfcn,nvars) x ga(fitnessfcn,nvars,A,b) x ga(fitnessfcn,nvars,A,b,Aeq,beq) x ga(fitnessfcn,nvars,A,b,Aeq,beg,IB,UB) x ga(fitnessfcn,nvars,A,b,Aeq,beq,LB,UB,nonlcon) x ga(fitnessfcn,nvars,A,b,Aeq,beq,LB,UB,nonlcon,options) x …...

基于STM32和MQ-2传感器的无线烟雾检测系统设计
随着科技的不断发展,人们对生活安全的要求也越来越高。其中,烟雾检测系统在预防火灾方面起着至关重要的作用。本文将介绍一种基于STM32和MQ-2传感器的无线烟雾检测系统设计,旨在实时检测环境中的烟雾,并及时发出警报,以…...

华为vrrp+mstp+ospf+dhcp+dhcp relay配置案例
1、左边是vlan 10主桥,右边是vlan 20的主桥,并且互为备桥 2、 vlan 10 vrrp网关默认用左边,vlan 20的vrrp 网关默认用右边,对应mstp生成树 3、两边都track检测,不通就把vrrp减掉60,这样就会自动切另一边了 …...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...