我们的商业模式中有一个学生班。令我感到奇怪的是,如果我们操纵另一名学生的一名学生,学生的私人成员是可见的......这让我觉得有些不雅:)
class Program {
static void Main(string[] args) {
Student s1 = new Student();
Student s2 = new Student();
s1.ExamineStudentsMembers(s2);
}
}
public class Student {
private String _studentsPrivateMember;
public Student() {
_studentsPrivateMember = DateTime.Now.Ticks.ToString();
}
public void ExamineStudentsMembers(Student anotherStudent) {
//this seems very wrong
Console.WriteLine(anotherStudent._studentsPrivateMember);
}
}
我是否可以对此设计考虑/含义有所了解。您似乎无法隐藏兄弟姐妹的信息。有没有办法将字段或成员标记为对同一类的其他实例隐藏?
答案 0 :(得分:9)
有一种简单的方法可以确保这一点:
不要乱用同一类别的其他实例的私有成员。
说真的 - 你是那个写Student
代码的人。
答案 1 :(得分:8)
确保这一点的最简单方法是编程到接口,例如:
class Program
{
static void Main(string[] args)
{
IStudent s1 = new Student();
IStudent s2 = new Student();
s1.ExamineStudentsMembers(s1);
}
}
public interface IStudent
{
void ExamineStudentsMembers(IStudent anotherStudent);
}
public class Student : IStudent
{
private string _studentsPrivateMember;
public Student()
{
_studentsPrivateMember = DateTime.Now.Ticks.ToString();
}
public void ExamineStudentsMembers(IStudent anotherStudent)
{
Console.WriteLine(anotherStudent._studentsPrivateMember);
}
}
由于ExamineStudentsMembers试图访问私有字段,因此将不再编译。
答案 2 :(得分:5)
如果您正在编写该类,则可以完全控制它,因此如果您不希望一个对象能够修改另一个对象,请不要写入该功能。
类通常会在其他实例中使用私有变量来实现有效的比较和复制功能。
答案 3 :(得分:4)
答案 4 :(得分:2)
如下所示,访问兄弟的私人数据似乎有误:
public void ExamineStudentsMembers(Student anotherStudent) {
//this seems very wrong
Console.WriteLine(anotherStudent._studentsPrivateMember);
}
然而,对于需要这种功能的方法来说,这似乎并不那么奇怪。什么方法需要访问兄弟的私人数据?比较方法(特别是等于)和数据结构中的对象(比如树或链表)。
比较方法通常直接比较私人数据而不仅仅是公共数据。
对于组成链接列表,图形或树的一类节点,能够访问兄弟的私有数据正是所需要的。知道中的代码(类的一部分)可以修改数据结构,但数据结构之外的代码不能触及内部。
值得注意的是,这两种情况在日常编程中不如首次开发此语言功能时那么常见。早在20世纪90年代和21世纪初,在C ++中构建自定义数据结构和比较方法就更为常见。也许现在是重新考虑私人成员的好时机。
答案 5 :(得分:2)
我喜欢第二点,你可以看一下,但不要碰这些私人会员。
有趣的是你应该这样说,我曾经认识一位老师,他说他经常遇到一个问题,决定哪些课程可以看看会员以及哪些课程实际上可以和他们一起玩。
答案 6 :(得分:1)
对象只是一个数据;该类包含该功能。成员方法只是编译器播放的一个很好的技巧;它更像是一个带有隐含参数的静态方法(有点像扩展方法)。考虑到这一点,保护对象彼此没有任何意义;你只能保护彼此的课程。因此它以这种方式运作是很自然的。
答案 7 :(得分:0)
不,这是必要的,方法代码不是特定于实例的,它只是特定于对象的类型。 (虚方法)或变量的声明类型(对于非虚方法)。另一方面,非静态字段是特定于实例的...这就是您具有实例级隔离的地方。
静态方法和非静态方法之间的唯一区别是不允许静态方法访问其他基于实例的(非静态)方法或字段。任何可以在不修改的情况下变为静态的方法都不会受到任何影响,方法是将其设置为静态,除非强制编译器在使用基于实例的语法调用的任何地方抛出错误。
答案 8 :(得分:0)
如果您打算检查给定学生的信息,那么我会将方法更改为静态:
public static void ExamineStudentsMembers(Student student)
{
Console.WriteLine(student._studentsPrivateMember);
}
然后您将使用Student.ExamineStudentsMembers(s1)
。使用s1.ExamineStudentsMembers(s2)
将无效。
如果这不是预期目的,我会将方法重写为:
public void ExamineStudentsMembers()
{
Console.WriteLine(_studentsPrivateMember);
}
然后通过编写s1.ExamineStudentsMembers()
答案 9 :(得分:0)
私人成员将隐藏客户端的实施细节。客户端应该只能看到接口(公共方法/字段/属性)。
目的不是为了保护程序员免受他自己的伤害。
这也不是安全功能,因为您始终可以通过反射访问私有字段。
真的要分离界面&实施(黑匣子设计),以及客户根据合同编程(所有公共领域)。
例如,如果您有一个公共获取属性,它可以直接访问某个私有字段,或者它可以从其他一些字段计算值。 目的是,客户端只知道合同(公共财产),并且可以在不影响客户端的情况下更改实施
答案 10 :(得分:-1)
对象范围 不 永远意味着安全!操作系统的角色是提供运行时安全性。设计一个依赖于特定于语言的对象作用域来限制运行时对象实例数据访问的系统是一个错误。如果情况并非如此,那么根据定义,所有非OO语言都不安全。