为啥有类级访问修饰符而不是对象级?

Posted

技术标签:

【中文标题】为啥有类级访问修饰符而不是对象级?【英文标题】:Why have class-level access modifiers instead of object-level?为什么有类级访问修饰符而不是对象级? 【发布时间】:2013-04-27 14:38:41 【问题描述】:

在使用 C# 时,我最近意识到我可以从 Foo 的静态函数,甚至从其他 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】:

private 修饰符强制执行Encapsulation 原则。

这个想法是“外部世界”不应该更改 AClass 内部流程,因为 AClass 实现可能会随着时间而改变(并且您必须改变整个外部世界以修复实现中的差异 - 这几乎是不可能的) .

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

然而,在其他一些语言中,private 在实例级别上工作,但在 C# 中却不是这样。

【讨论】:

我不明白为什么这里没有 cmets,至少应该有人说谢谢。好吧,谢谢,这清除了它。 @Martin Upvote 足以表示感谢 :) 基本上它取代了“+1”答案等。【参考方案2】:

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

如果您有一个需要访问另一个实例的私有成员的 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()的原因吗? 是的@Arno,或者 Object.Equals(object otherObject) 这实际上是使用其他实例的私有成员的一个很好的例子。 @ArnoSluismans 对于两个对象,以下可能为真:A.GetHashCode() == B.GetHashCode(),但 A.Equals(B) == 假。【参考方案3】:

Private 成员只能从该类范围内的所有其他成员访问。无论是由多个实例还是一个实例完成都没有关系。

您试图限制成员只能从this. 调用,因此不允许从外部调用它们(从实例的角度来看),但允许调用一次您已进入实例的范围。这在 C# 中根本不可能。

虽然会是一个不错的功能... :)

【讨论】:

【参考方案4】:

private (C# Reference) 话题说:

private 关键字是成员访问修饰符。私人访问是 最低许可访问级别。私有成员只能访问 在声明它们的类或结构体中 (...)

更多:

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

所以下面的代码可以完美运行。

class Foo

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

关于“为什么”类有访问修饰符而不是对象的问题,这是在 OOP 中隐藏信息的一种方式(阅读更多关于Encapsulation (object-oriented programming)。

我还建议您阅读这些章节:

10.5 会员访问 17.2.3 访问修饰符

Standard ECMA-334 C# Language Specification。

【讨论】:

【参考方案5】:

private 意味着您只能从类本身访问它。不管是静态的还是静态的,都没有区别。虽然这条规则也不例外……

克里斯托夫

【讨论】:

【参考方案6】:

你可以访问私有方法的原因是因为你在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
    

所以基本上它...

Public - 如果你能看到类,那么你就能看到方法

Private - 如果你是班级的一员,那么你可以看到方法,否则不能。

【讨论】:

我知道这一点,正如我在帖子中指定的那样。问题是为什么它会这样工作。

以上是关于为啥有类级访问修饰符而不是对象级?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们不能在 Kotlin 的 Singleton 类(对象)中使用受保护的访问修饰符

有了private修饰符,为啥可以直接访问其他对象中的成员?

Scala基础:类和对象访问修饰符和构造器

为啥Java限制隐藏方法的访问修饰符[关闭]

C#:为啥我必须在类的变量中使用公共访问修饰符?

Java中的修饰符