C# 提供了internal关键来,来控制程序集的访问权限。但如果不提供dll的分发形式,internal的价值就无法体现出来。
在管理类和被管理对象之间,常常需要互相访问一些属性,这就破坏了封装性。因为这些属性,并不想被其它方法修改,但又不得不标记为公开。比如:
public class Tween
{
public float duration;
}
public static class TweenManager
{
private static List<Tween> tweenList = new List<Tween>();
public static void AddTime()
{
foreach (var tween in tweenList)
{
// 修改被管理对象的字段,而这个字段不想被其它对象修改
tween.duration += 10.0f;
}
}
}
如上设计,经常在一个功能的一组类之间出现。除了把duration定义为internal生成dll,要么就写注释,其它没有办法控制duration的访问权限,仅仅是TweenManager之内。
下面,我发现了一个办法,稍微有一点繁琐,但基本可以不使用internal的情况下,稍稍控制一下访问权限。如下:
public class Tween
{
// 继承可构造
protected Tween()
{
}
// 继承可见
protected float duration;
}
public static TweenManager
{
public class TweenVisit : Tween
{
protected TweenVisit() : base() {}
public static TweenVisit Get()
{
return new TweenVisit();
}
// 返回受保护的字段
public float Duration
{
get { return this.duration; }
}
}
// 子类当父类返回
public static Tween GetTween()
{
return TweenVisit.Get();
}
// 内部持有的是TweenVisit对象,可以访问Tween受保护的字段,但是外界拿到的是Tween,无法访问protected字段
private static List<TweenVisit> tweenList = new List<TweenVisit>();
}
通过这种方法,TweenVisit可以访问Tween的protected属性,但是并不对外公开TweenVisit,仅仅留作TweenManager内部使用,起到了保护的作用。
当然,TweenVisit也可以是private class,这样外界就不能用TweenVisit类型来强转Tween获得访问权限了。
Tween所有只希望被TweenManager访问的字段,都可以用protected标记,在TweenVisit中public给TweenManager使用。