introduction
As a newcomer to the field of programming from the nursing industry, I have found that the concept of object-oriented programming (OOP) actually has many similarities to medical practice. In this article, I will share how I understand the basic concepts of object-oriented programming through my medical work experience, hoping to help other medical professionals who are learning to program.
Process-oriented vs object-oriented
process-oriented thinking
Process-oriented programming focuses on the process and steps to get things done, and emphasizes actions and processes. It's like the standard operating procedures (SOPs) we implement in hospitals.
For example, process-oriented thinking for measuring a patient's blood sugar:
// 面向过程思维:不同护士执行相同的血糖测量流程
void NurseLiMeasureBloodSugar() // 李护士(经验少)
{
PrepareEquipment(); // 准备设备
CallForHelp(); // 寻求帮助
ExplainToPatient(); // 向患者解释
DisinfectFinger(); // 消毒手指
PrickFinger(); // 采血
ApplyBloodToStrip(); // 血液滴到试纸
ReadResult(); // 读取结果
RecordData(); // 记录数据
DisposeMaterials(); // 处理医疗废物
}
void NurseZhangMeasureBloodSugar() // 张护士(经验丰富)
{
PrepareEquipment(); // 准备设备
ExplainToPatient(); // 向患者解释
DisinfectFinger(); // 消毒手指
PrickFingerExpertly(); // 熟练采血
ApplyBloodToStrip(); // 血液滴到试纸
ReadResultAccurately(); // 精确读取结果
RecordDataInDetail(); // 详细记录数据
DisposeMaterials(); // 处理医疗废物
}
It can be seen that the process-oriented approach requires us to write different code for different executors, and each nurse needs her own complete process, making the code repetitive and difficult to maintain.
object-oriented thinking
Object-oriented programming is about finding an object to help you do things. For the same blood sugar measurement task, we shifted our attention from "who does it" to "what equipment does it with" and encapsulated the operations into the corresponding objects.
/// <summary>
/// 血糖仪类 - 负责测量和记录血糖值的医疗设备
/// </summary>
public class GlucoseMeter
{
// 属性 - 表示血糖仪的状态
/// <summary>
/// 表示血糖仪是否已校准
/// </summary>
public bool IsCalibrated { get; private set; }
/// <summary>
/// 表示血糖仪当前电量
/// </summary>
public double BatteryLevel { get; private set; }
// 方法 - 表示血糖仪可执行的操作
/// <summary>
/// 校准血糖仪,确保测量准确
/// </summary>
public void Calibrate()
{
IsCalibrated = true;
Console.WriteLine("血糖仪已校准");
}
/// <summary>
/// 执行血糖测量
/// </summary>
/// <returns>测量的血糖值,若设备未校准则返回-1</returns>
public double MeasureBloodSugar()
{
if(!IsCalibrated)
{
Console.WriteLine("错误:血糖仪未校准");
return -1; // 错误值
}
Console.WriteLine("测量血糖中...");
// 执行测量逻辑
return 5.6; // 返回血糖值(示例)
}
}
/// <summary>
/// 护士类 - 代表执行医疗操作的护理人员
/// </summary>
public class Nurse
{
/// <summary>
/// 护士姓名
/// </summary>
public string Name { get; private set; }
/// <summary>
/// 工作经验年限
/// </summary>
public int ExperienceYears { get; private set; }
/// <summary>
/// 创建一个新的护士对象
/// </summary>
/// <param name="name">护士姓名</param>
/// <param name="experienceYears">工作经验年限</param>
public Nurse(string name, int experienceYears)
{
Name = name;
ExperienceYears = experienceYears;
}
/// <summary>
/// 为患者测量血糖的综合操作
/// </summary>
/// <param name="patient">需要测量的患者</param>
/// <param name="meter">使用的血糖仪</param>
public void MeasurePatientBloodSugar(Patient patient, GlucoseMeter meter)
{
Console.WriteLine($"{Name}护士准备为{patient.Name}测量血糖");
// 准备设备
Console.WriteLine("准备设备");
// 校准设备(由血糖仪完成)
meter.Calibrate();
// 向患者解释
Console.WriteLine($"向{patient.Name}解释测量过程");
// 消毒和采血(护士的专业操作)
Console.WriteLine("消毒手指并采血");
// 测量血糖(由血糖仪完成)
double bloodSugar = meter.MeasureBloodSugar();
// 记录结果
if(bloodSugar > 0)
{
patient.RecordBloodSugar(bloodSugar);
Console.WriteLine($"血糖值: {bloodSugar}mmol/L,已记录到患者档案");
}
// 处理医疗废物
Console.WriteLine("处理医疗废物");
}
}
/// <summary>
/// 患者类 - 代表医院中的病人
/// </summary>
public class Patient
{
// 字段 - 私有数据,不直接对外暴露
/// <summary>
/// 患者姓名
/// </summary>
private string _name;
/// <summary>
/// 患者年龄
/// </summary>
private int _age;
/// <summary>
/// 患者的历史血糖记录
/// </summary>
private List<double> _bloodSugarReadings;
/// <summary>
/// 创建一个新的患者对象
/// </summary>
/// <param name="name">患者姓名</param>
/// <param name="age">患者年龄</param>
public Patient(string name, int age)
{
_name = name;
_age = age;
_bloodSugarReadings = new List<double>(); // 初始化空的血糖记录列表
}
// 属性 - 对外提供的访问器
/// <summary>
/// 获取患者姓名
/// </summary>
public string Name
{
get { return _name; }
private set { _name = value; } // 只允许在类内部修改
}
/// <summary>
/// 获取或设置患者年龄(包含验证)
/// </summary>
public int Age
{
get { return _age; }
private set { _age = value > 0 ? value : 0; } // 确保年龄为正数
}
// 方法 - 对象可执行的操作
/// <summary>
/// 记录新的血糖测量值
/// </summary>
/// <param name="value">血糖值</param>
public void RecordBloodSugar(double value)
{
if(value > 0)
{
_bloodSugarReadings.Add(value);
}
}
/// <summary>
/// 获取最近一次血糖记录
/// </summary>
/// <returns>最近的血糖值,如无记录则返回-1</returns>
public double GetLatestBloodSugar()
{
if(_bloodSugarReadings.Count > 0)
return _bloodSugarReadings[_bloodSugarReadings.Count - 1];
else
return -1; // 表示没有记录
}
/// <summary>
/// 获取患者的所有血糖记录历史
/// </summary>
/// <returns>血糖值列表的副本</returns>
public List<double> GetBloodSugarHistory()
{
return new List<double>(_bloodSugarReadings); // 返回副本以保护原始数据
}
}
// 使用示例 - 演示对象之间的协作
/// <summary>
/// 血糖测量的综合示例
/// </summary>
void BloodSugarMeasurementExample()
{
// 创建各种对象
Patient patient = new Patient("王小明", 65);
GlucoseMeter meter = new GlucoseMeter();
// 不同经验的护士使用相同的方法和设备
Nurse nurseLi = new Nurse("李护士", 1); // 经验少
Nurse nurseZhang = new Nurse("张护士", 10); // 经验丰富
// 两位护士执行相同的操作,调用相同的方法
nurseLi.MeasurePatientBloodSugar(patient, meter);
nurseZhang.MeasurePatientBloodSugar(patient, meter);
// 检查患者的血糖历史
List<double> history = patient.GetBloodSugarHistory();
Console.WriteLine($"患者{patient.Name}的血糖记录次数: {history.Count}");
}
Through an object-oriented approach, we:
- Objects were created to represent different roles and devices (patient, nurse, blood glucose meter)
- Each subject is responsible for its own functions (the blood glucose meter is responsible for the measurement, the nurse is responsible for the operating process)
- No matter which nurse they are, they use the same method, reducing code duplication
- Assign responsibilities to the right objects, making the code more modular and easier to maintain
It's like real medical work: different nurses use the same medical equipment and standard processes to serve patients, rather than every nurse inventing his own process.
Understand classes and objects
When working in hospitals, we have a template called "Nursing Record Sheet", based on which we can create specific records for each patient. In programming:
- ** Class **: Just like the nursing record template, it defines the characteristics (attributes) and functions (methods) that the object should have
- ** Object **: Just like a specific patient record filled in based on a template
The concept of class
A class is like a drawing or mold, like the nursing evaluation form I used when I was a nurse. This table defines the content (attributes) and the operation process (methods) that need to be recorded.
In C#, the basic syntax of classes is:
[public] class 类名
{
// 字段
private string _name;
// 属性
public string Name
{
get { return _name; }
set { _name = value; }
}
// 方法
public void DoSomething()
{
// 方法实现
}
}
Relationship between classes and objects
If you use the analogy as a medical record template, then the object is the specific patient record created based on this template. Classes themselves do not consume memory (except for static members), objects do.
Medical examples:
// Patient类(病人类)
public class Patient
{
// 字段
private string _name;
private int _age;
private string _diagnosis;
// 属性
public string Name
{
get { return _name; }
set { _name = value; }
}
public int Age
{
get { return _age; }
set { _age = value > 0 ? value : 0; } // 验证年龄必须为正数
}
// 方法
public void TakeMedicine()
{
Console.WriteLine($"{Name}正在服药...");
}
}
// 创建Patient对象
Patient patient1 = new Patient();
patient1.Name = "张三";
patient1.Age = 45;
patient1.TakeMedicine(); // 输出:张三正在服药...
Understand attributes and fields
Differences between fields and attributes
In nursing work, we have a lot of data to record, but some data needs to be verified or specially processed.
- ** Field **: Equivalent to the raw data on the medical record. It should usually be protected and no external direct modification is allowed
- ** Attribute **: Equivalent to a control mechanism for these data, verification logic can be added
public class Patient
{
// 字段(私有)
private double _temperature;
// 属性(公开)
public double Temperature
{
get { return _temperature; }
set
{
// 添加验证逻辑
if(value >= 35 && value <= 42)
_temperature = value;
else
throw new ArgumentException("体温数值不合理!");
}
}
}
属性的本质是两个方法:get()和set()。属性可以是:
- Readable and writable attributes: get and set
- Read-only attribute: only get
- Write attribute only: only set
access modifiers
In the hospital information system, the information that different levels of personnel can access is different. This is similar to the access modifier concept in C#:
public:公开的,就像病人的基本信息,所有医护人员都可以查看private:私有的,只能在当前类内部访问,就像某些敏感检查结果,只有主治医生可以查看protected:受保护的,可以被派生类访问,就像某些治疗方案,只有医疗团队成员可以查看
Initialization of objects
When a new patient is admitted, we need to fill out a series of forms to record basic information. In programming, we use the ** constructor ** to complete the initialization of objects.
constructor
The constructor is a special method that is automatically executed when the object is created and used to initialize the object.
public class Patient
{
// 字段
private string _name;
private int _age;
// 构造函数
public Patient(string name, int age)
{
_name = name;
_age = age;
Console.WriteLine($"创建了一个新病人: {name}, {age}岁");
}
// 属性
public string Name
{
get { return _name; }
set { _name = value; }
}
public int Age
{
get { return _age; }
set { _age = value; }
}
}
// 使用构造函数创建对象
Patient newPatient = new Patient("李四", 50);
Characteristics of the constructor:
- There is no return value, and you cannot even write void
- Name must be the same as class name
- Multiple overloaded versions can be available
- There is a parameterless constructor by default in the class, but if you customize the constructor, the default parameterless constructor disappears
The role of new keywords
当我们使用new创建对象时,它做了三件事:
- Open up space in memory
- Create objects in this space
- Call the constructor of the object to initialize
It's like a hospital allocating beds to new patients, preparing medical records, and then entering basic information.
Static and non-static
In hospitals, some information is different for each patient (such as name, age), and some information is shared by all patients (such as hospital name, department doctor).
Static members and instance members
- ** Instance member **: Unique attributes or methods for each object, just like each patient has his own body temperature, blood pressure and other data
- ** Static member **: A property or method that belongs to the class itself rather than the object, shared by all objects, like hospital names, treatment specifications, etc.
/// <summary>
/// 医院类(静态) - 包含所有科室共享的医院级信息
/// </summary>
public static class Hospital
{
// 静态属性 - 所有科室共享
/// <summary>
/// 医院名称 - 所有科室共享
/// </summary>
public static string Name { get; } = "和平医院";
/// <summary>
/// 总床位数 - 由所有科室共用
/// </summary>
public static int TotalBeds { get; private set; } = 500;
/// <summary>
/// 医院地址 - 所有科室共享
/// </summary>
public static string Address { get; } = "和平路123号";
/// <summary>
/// 急诊电话 - 所有科室共享
/// </summary>
public static string EmergencyNumber { get; } = "120";
// 静态方法 - 医院级别的操作
/// <summary>
/// 患者入院流程 - 分配到特定科室
/// </summary>
/// <param name="patient">入院患者</param>
/// <param name="department">目标科室</param>
public static void AdmitPatient(Patient patient, Department department)
{
if(TotalBeds > 0)
{
department.AssignBed(patient);
TotalBeds--;
Console.WriteLine($"{patient.Name}已入院到{department.Name}科");
}
else
{
Console.WriteLine("医院床位已满,无法入院");
}
}
/// <summary>
/// 患者出院流程 - 从特定科室出院
/// </summary>
/// <param name="patient">出院患者</param>
/// <param name="department">来源科室</param>
public static void DischargePatient(Patient patient, Department department)
{
department.ReleaseBed(patient);
TotalBeds++;
Console.WriteLine($"{patient.Name}已从{department.Name}科出院");
}
}
/// <summary>
/// 科室类 - 表示医院中的具体科室,每个科室有自己的特性
/// </summary>
public class Department
{
// 字段 - 科室特有数据
/// <summary>
/// 科室名称
/// </summary>
private string _name;
/// <summary>
/// 科室总床位数
/// </summary>
private int _totalBeds;
/// <summary>
/// 科室可用床位数
/// </summary>
private int _availableBeds;
/// <summary>
/// 科室医护人员ID列表
/// </summary>
private List<string> _staffIds;
/// <summary>
/// 科室当前病人列表
/// </summary>
private List<Patient> _patients;
/// <summary>
/// 创建一个新的科室
/// </summary>
/// <param name="name">科室名称</param>
/// <param name="totalBeds">总床位数</param>
public Department(string name, int totalBeds)
{
_name = name;
_totalBeds = totalBeds;
_availableBeds = totalBeds;
_staffIds = new List<string>();
_patients = new List<Patient>();
}
// 属性 - 科室对外暴露的信息
/// <summary>
/// 获取科室名称
/// </summary>
public string Name { get { return _name; } }
/// <summary>
/// 获取科室可用床位数
/// </summary>
public int AvailableBeds { get { return _availableBeds; } }
// 方法 - 科室可执行的操作
/// <summary>
/// 为患者分配床位
/// </summary>
/// <param name="patient">需要床位的患者</param>
public void AssignBed(Patient patient)
{
if(_availableBeds > 0)
{
_patients.Add(patient);
_availableBeds--;
Console.WriteLine($"{patient.Name}已分配到{_name}科床位");
}
else
{
Console.WriteLine($"{_name}科床位已满");
}
}
/// <summary>
/// 患者出院释放床位
/// </summary>
/// <param name="patient">出院患者</param>
public void ReleaseBed(Patient patient)
{
if(_patients.Contains(patient))
{
_patients.Remove(patient);
_availableBeds++;
Console.WriteLine($"{patient.Name}已释放{_name}科床位");
}
}
/// <summary>
/// 添加医护人员到本科室
/// </summary>
/// <param name="staffId">医护人员ID</param>
public void AddStaff(string staffId)
{
_staffIds.Add(staffId);
}
/// <summary>
/// 显示科室当前状态信息
/// </summary>
public void DisplayDepartmentStatus()
{
// 这里同时访问静态成员(医院名)和实例成员(科室信息)
Console.WriteLine($"{Hospital.Name} - {_name}科");
Console.WriteLine($"总床位:{_totalBeds},可用床位:{_availableBeds}");
Console.WriteLine($"当前患者数:{_patients.Count}");
}
}
the this keyword
this关键字表示当前类的实例,在医护工作中,可以理解为"当前正在处理的这个病人"。
Purpose of this:
- Distinguish between local variables and member variables
- Call other constructors in the constructor
public class Patient
{
private string name;
private int age;
// 使用this区分同名变量
public Patient(string name, int age)
{
this.name = name; // this.name是字段,name是参数
this.age = age;
}
// 使用this调用其他构造函数
public Patient(string name) : this(name, 0)
{
// 这个构造函数会先调用上面的构造函数
}
}
Example medication record
The following is a complete example of a medication record class that demonstrates the application of object-oriented programming in a medical scenario:
/// <summary>
/// 用药记录类 - 记录患者用药的详细信息
/// </summary>
public class MedicationRecord
{
// 字段 - 记录的内部数据
/// <summary>
/// 药品名称
/// </summary>
private string _medicationName;
/// <summary>
/// 药品剂量(数值部分)
/// </summary>
private double _dosage;
/// <summary>
/// 剂量单位(如mg, ml等)
/// </summary>
private string _unit;
/// <summary>
/// 给药时间
/// </summary>
private DateTime _administrationTime;
/// <summary>
/// 执行给药的护士ID
/// </summary>
private string _nurseId;
/// <summary>
/// 接受给药的患者ID
/// </summary>
private string _patientId;
/// <summary>
/// 给药途径(口服、静脉注射等)
/// </summary>
private string _route;
/// <summary>
/// 创建新的用药记录
/// </summary>
/// <param name="patientId">患者ID</param>
/// <param name="medicationName">药品名称</param>
/// <param name="dosage">药品剂量</param>
/// <param name="unit">剂量单位</param>
/// <param name="route">给药途径</param>
/// <param name="nurseId">执行护士ID</param>
public MedicationRecord(string patientId, string medicationName,
double dosage, string unit, string route, string nurseId)
{
_patientId = patientId;
_medicationName = medicationName;
_dosage = dosage;
_unit = unit;
_route = route;
_nurseId = nurseId;
_administrationTime = DateTime.Now; // 记录当前时间为给药时间
}
// 属性 - 对外部提供的数据访问接口
/// <summary>
/// 获取药品名称(只读)
/// </summary>
public string MedicationName { get { return _medicationName; } }
/// <summary>
/// 获取剂量(只读)
/// </summary>
public double Dosage { get { return _dosage; } }
/// <summary>
/// 获取剂量单位(只读)
/// </summary>
public string Unit { get { return _unit; } }
/// <summary>
/// 获取给药时间(只读)
/// </summary>
public DateTime AdministrationTime { get { return _administrationTime; } }
// 方法 - 记录相关的操作
/// <summary>
/// 获取完整的剂量信息
/// </summary>
/// <returns>格式化的剂量和给药途径信息</returns>
public string GetFullDosageInfo()
{
return $"{_dosage} {_unit} {_medicationName} 通过{_route}给药";
}
/// <summary>
/// 获取完整的给药记录
/// </summary>
/// <returns>格式化的完整给药记录</returns>
public string GetAdministrationRecord()
{
return $"患者ID: {_patientId}, 药品: {_medicationName}, " +
$"剂量: {_dosage}{_unit}, 途径: {_route}, " +
$"时间: {_administrationTime.ToString("yyyy-MM-dd HH:mm:ss")}, " +
$"执行护士: {_nurseId}";
}
/// <summary>
/// 检查是否在指定时间阈值内给药
/// </summary>
/// <param name="hoursThreshold">小时阈值</param>
/// <returns>如果在阈值内返回true,否则返回false</returns>
public bool IsAdministeredRecently(int hoursThreshold)
{
return (DateTime.Now - _administrationTime).TotalHours < hoursThreshold;
}
}
// 使用示例
public class MedicationExample
{
public static void Main()
{
// 创建用药记录
MedicationRecord record = new MedicationRecord(
"P001", "阿司匹林", 100, "mg", "口服", "N007");
// 获取完整记录
string fullRecord = record.GetAdministrationRecord();
Console.WriteLine(fullRecord);
// 检查是否最近给药(6小时内)
bool isRecent = record.IsAdministeredRecently(6);
Console.WriteLine($"是否6小时内给药: {isRecent}");
}
}
summary
As a novice from nurse to programming, I have found many similarities between the concept of object-oriented programming and medical practice:
- ** Category ** is like a medical record form template
- ** Object ** is like a specific patient's medical record
- ** Attributes ** are like patient indicators, some of which require data verification
- ** Methods ** are like various medical procedures performed on patients
- ** Constructor ** is like patient admission
- ** Static members ** are like shared resources and norms for hospitals
Through these analogies, it is easier for me to understand and remember the concepts of object-oriented programming. In the next article, I will continue to delve into advanced concepts of object-oriented programming, such as inheritance, polymorphism, and interfaces.
Looking forward to sharing more learning experiences from medical care to programming with you!