如何实现Person类的Teacher、Student两个属性仅可赋值其中一个?
你要的需求可以通过角色接口的方式实现,既满足直接创建Person对象的要求,也能保证每个Person只能对应教师/学生其中一个身份,完全符合你期望的实例化写法,具体实现如下:
1. 定义身份公共接口
首先定义一个空的身份标记接口,让Teacher和Student都实现该接口,作为Person类中身份属性的统一类型:
// 身份标记接口 public interface IPersonRole { }
2. 实现教师、学生类
两个类分别实现IPersonRole接口,保留各自的专属属性:
public class Teacher : IPersonRole { // 教师专属属性 public string TeacherId { get; set; } public DateTime HireDate { get; set; } public string Subject { get; set; } } public class Student : IPersonRole { // 学生专属属性 public string StudentId { get; set; } public string ClassName { get; set; } public double AverageScore { get; set; } }
3. 改造Person类
在Person类中用IPersonRole类型存储身份,构造函数强制传入身份实例,从根源上保证每个Person有且仅有一个合法身份:
public class Person { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string PhoneNumber { get; set; } // 身份属性,对外只读禁止随意修改 public IPersonRole Role { get; private set; } public Person(int id, string firstName, string lastName, string phoneNumber, IPersonRole role) { Id = id; FirstName = firstName; LastName = lastName; PhoneNumber = phoneNumber; // 校验身份合法性 if (role == null) throw new ArgumentNullException(nameof(role)); if (role is not Teacher && role is not Student) throw new ArgumentException("身份只能为教师或学生", nameof(role)); Role = role; } // 辅助属性,快速判断身份类型 public bool IsTeacher => Role is Teacher; public bool IsStudent => Role is Student; // 辅助方法,安全转换身份类型,避免强制转换报错 public Teacher GetTeacher() => Role as Teacher; public Student GetStudent() => Role as Student; }
4. 按你期望的方式实例化
完全符合你要的调用写法:
// 实例化教师身份的Person Person teacherPerson = new Person(1, "Hans", "Klok", "0636257135", new Teacher { TeacherId = "T001", HireDate = new DateTime(2020, 9, 1), Subject = "物理" }); // 实例化学生身份的Person Person studentPerson = new Person(2, "Hans", "Klok", "0636257135", new Student { StudentId = "S2024003", ClassName = "高一2班", AverageScore = 91.5 });
5. 使用示例
调用时可以快速判断身份并获取专属属性:
if (teacherPerson.IsTeacher) { var teacher = teacherPerson.GetTeacher(); Console.WriteLine($"教师授课科目:{teacher.Subject}"); } if (studentPerson.IsStudent) { var student = studentPerson.GetStudent(); Console.WriteLine($"学生平均成绩:{student.AverageScore}"); }
这个方案比你最初设想的同时定义Teacher和Student两个属性的写法更严谨,完全避免了两个属性同时赋值、或者都为空的非法情况,也满足所有业务要求。
内容的提问来源于stack exchange,提问作者KaasGierInFrankrijk
相关产品推荐
相关产品推荐

