为什么要使用类级别的访问修饰符而不是对象级别的?

26

最近我使用 C# 时意识到,我可以从 Foo 的静态函数甚至其他 Foo 对象中调用私有函数。在我学习访问修饰符的所有知识后,这听起来非常奇怪。

据我所知,当一个函数执行某种内部过程时,你会将它设为私有。只有对象本身知道何时使用这些函数,因为其他对象不应该/不能控制该对象的流程。难道同一类的其他对象有任何理由例外于这个非常直观的规则吗?

根据要求,以下是一个示例:

public class AClass {
    private void doSomething() { /* Do something here */ }
    public void aFunction() {
        AClass f = new AClass();
        f.doSomething(); // I would have expected this line to cause an access error.
    }
}

1
我不确定你在这里描述的是什么。你能发一些例子吗? - Alex Filipovici
在同一个类中的静态方法中,如果没有对象引用,你不能调用非静态方法。 - John Willemse
6个回答

59

private修饰符强制执行封装原则

这个想法是,'外部世界'不应该修改AClass的内部过程,因为AClass的实现可能随着时间的推移而改变(你将不得不改变整个外部世界来解决实现差异 - 这几乎是不可能的)。

当AClass的实例访问其他AClass实例的内部时,您可以确定两个实例始终知道AClass的实现细节。如果AClass内部的逻辑处理发生了变化 - 您只需更改AClass的代码即可。

然而,在某些其他语言中,private在实例级别上运作,但这在C#中并不是真的。


17

当您将成员设置为私有时,它对其他类是私有的,而不是对该类本身。

例如,如果您有一个需要访问另一个实例的私有成员的Equals方法,则可以很有用:

public class AClass
{
    private int privateMemberA;

    // This version of Equals has been simplified
    // for the purpose of exemplifying my point, it shouldn't be copied as is
    public override bool Equals(object obj)
    {
        var otherInstance = obj as AClass;
        if (otherInstance == null)
        {
            return null;
        }

        return otherInstance.privateMemberA == this.privateMemberA;
    }
}

难道这不是我们为什么有 Object.GetHashCode() 的原因吗? - Lee White
是的 @Arno,或者Object.Equals(object otherObject),这实际上是使用其他实例的私有成员的很好的例子。 - Sam Bauwens
@ArnoSluismans 对于两个对象,可能出现以下情况:A.GetHashCode() == B.GetHashCode(),但 A.Equals(B) == false。 - Artemix

1

private (C# 参考) 主题中说:

private 关键字是成员访问修饰符。private 访问是最不宽松的访问级别。私有成员只能在声明它们的类或结构体的主体内部访问 (...)

更进一步:

在同一主体中的嵌套类型也可以访问这些私有成员。

因此,以下代码将完美地工作。

class Foo
{
    private void PrivateMethod()
    {
    }
    class FooBaby
    {
        public static void MethodB()
        {
            Foo foo = new Foo();
            foo.PrivateMethod();
        }
    }
}

关于问题“为什么”类具有访问修饰符而对象没有,这是面向对象编程中信息隐藏的一种方式之一(请阅读更多关于封装(面向对象编程)的内容)。
我还建议您阅读以下章节:
  • 10.5 成员访问
  • 17.2.3 访问修饰符
C#语言规范标准ECMA-334

1

Private 成员只能在该类的作用域内从其他成员中访问。无论是通过多个实例还是一个实例完成此操作都没有关系。

您正在尝试将成员限制为仅从 this. 调用,因此它们不允许从外部世界调用(从实例的角度来看),但是一旦进入实例的作用域,它们就被允许被调用。在 C# 中这是不可能的。

虽然这将是一个很好的功能... :)


0

你可以访问私有方法的原因是因为你在 AClass 内部。

例如,如果你创建一个 BClass 并在其中创建一个 AClass,你将无法访问私有方法。

public class AClass
{
    private void doSomething() { /* Do something here */ }
    public void aFunction()
    {
        AClass f = new AClass();
        f.doSomething(); // we are inside AClass so we can access
    }
}

public class BClass
{
    private void doSomething() { /* Do something here */ }
    public void aFunction()
    {
        AClass f = new AClass();
        f.doSomething(); // Will not compile because we are outside AClass
    }
}

基本上来说...

公共的 - 如果你可以看到这个类,那么你就能看到这个方法。

私有的 - 如果你是这个类的一部分,那么你就能看到这个方法;否则不能。


我知道这一点,因为我在我的帖子中指定了。问题是为什么它会以这种方式工作。 - Lee White

0

private表示只能从类本身访问。它是静态的还是非静态的并没有区别。虽然这个规则也没有例外...

克里斯托夫


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接