问题
I'm wondering why this works?
For example I have some executor class that looks like so:
public class Executor
{
public void Execute(Action action)
{
action();
}
}
Now I have some need to be executed class that looks like:
public class NeedToBeExecuted
{
public void Invoke()
{
Executor executor = new Executor();
executor.Execute(DoSomething);
}
private void DoSomething()
{
// do stuff private
}
}
My question is why this is work's I pass a private method to other class?
Is this not an encapsulation issue?
回答1:
No, this is not a violation of encapsulation.
First off: the class itself is the thing that decided to hand out a delegate to one of its private methods! The class has access to its private methods and if it chooses to hand a reference to one to code outside of the accessibility domain of that method, that's perfectly within its rights.
Second: the accessibility domain of a method doesn't restrict where the method can be called. It restricts where the method can be looked up by name. Class Executor
is never using the name DoSomething
to invoke the private method. It's using the name action
.
回答2:
Let me give it a try then.
No we don't have an encapsulation issue. You are defining a class that is responsible to Execute
something. The Executer
knows nothing about what actually is executed. It only knows that it should execute DoSomething
. What DoSomething
does is specified in the class that is responsible to have something executed.
As I commented, it's quite similar to what you would do with a Thread
. You define a method that needs to be executed on a different Thread. That's why the class has a Thread, and defines which method should be ran on that Thread. Thread still knows nothing about the class where it plays a role in.
The relations are Class => Thread. Not the other way around.
In your example, the relations are NeedToBeExecuted
=> Executer
. Not the other way around.
The concept can be tricky to your mind, but you are doing nothing wrong.
回答3:
It's only as much of an encapsulation issue as using reflection is. It's possible to get access to private methods and variables from an external class quite easily using reflection. You shouldn't consider this a bad thing necessarily as it just makes the language all that much more powerful.
The class is the one giving up the delegate method anyway, so in a way the class is enabling the behaviour so it shouldn't be an encapsulation issue at all.
回答4:
Consider this: NeedToBeExecuted
is not exposing the DoSomething()
method in such a way that it can be called arbitrarily - instead it is passing it as a delegate to another function. It could just as easily be passing () => DoSomething()
- the result is the same. Ultimately access modifiers are there to prevent a different class using your method, you are still free to use it as you like. If you choose to pass it to another class, that's a valid use.
回答5:
Encapsulation means being able to change the internals of some module without changing external code. This is still the case here. So no encapsulation breach has occurred.
回答6:
You pass DoSomething
in the method Invoke()
, and it is accessible in the context. There's no encapsulation issue.
However, as you see the comment in the code, DoSomething
is not accessible in EitherNeedToBeExecuted
.
public class Executor {
public void Execute(Action action) {
action();
}
}
public class NeedToBeExecuted {
public virtual void Invoke() {
Executor executor=new Executor();
executor.Execute(this.DoSomething);
}
private void DoSomething() {
Console.WriteLine("I'M DOING IT MYSELF!!");
}
protected Executor m_Executor=new Executor();
}
public class EitherNeedToBeExecuted: NeedToBeExecuted {
public override void Invoke() {
// 'NeedToBeExecuted.DoSomething()' is inaccessible due to its protection level
m_Executor.Execute(base.DoSomething);
}
}
来源:https://stackoverflow.com/questions/15586728/encapsulation-issue-with-delegates