动动手脚,protected不再被保护

今天看Delphi的e-book,看到在delphi中以一种违反访问权限规则的“欺骗”方式访问其父类。此时我想到一个问题,就是当protected对对象进行封装保护时,是有很明显的后门的。在C#中,我们很容易将protected暴露为public。例如:

 

class Base
    
{
        
protected void Print()
        
{
            Console.Write(
"This is protected method in Base Class!");
        }

    }


    
class Derived:Base
    
{
        
public new void Print()
        
{
            
base.Print();
        }

    }

通过这种方法,我们就可以在另外的类中毫无顾忌地访问Base的Print()方法了。

class OtherClass
    
{
        
        [STAThread]
        
static void Main(string[] args)
        
{
            Derived d 
= new Derived();
            d.Print();
            Console.ReadLine();
        }

    }

换句话说,如果我们想暴露某个类的受保护方法或字段,OK,我们只需要生成一个wrapper类(对使用者,就好比是包装了该类,实质上是采用继承的方法),派生这个类,然后new这个受保护方法,并将其定义为public就可以了。如此一种“欺骗”的方式,轻而易举就窃取了类的受保护方法。

也就是说,通过继承的方法,我们可以提升父类设置的访问级别。当然对于父类的private是无能为力的。

所以,对于派生类而言,是应该直接派生其受保护方法呢?还是应该new一个新的,需要我们根据实际情况来选择。

posted on 2004-11-17 16:26 张逸 阅读(2935) 评论(21)  编辑 收藏 所属分类: C# Programming

评论

#1楼  2004-11-17 16:33 umlchina      

呵呵,老兄
protected声明的方法本来就是为了让其子类可以使用
不让外部使用的方法你直接用private多简单

  回复  引用  查看    

#2楼 [楼主] 2004-11-17 16:36 wayfarer      

呵呵。我已经意识到这点,其实我想说的是派生类可以提升其父类的访问级别。

所以我已经改了,没想到你回复得这么快,呵呵^_^

  回复  引用  查看    

#3楼 [楼主] 2004-11-17 16:41 wayfarer      

还有一个问题是,这个父类并非你实现的。如果你需要将父类的某些方法暴露出来,那就需要这样动动手脚了。

因此你在设计类库时,为了保证重用的灵活性时,还是应多考虑使用protected,而不是private,即使你的目的是不想让外部调用。一旦声明为private,可就被封装死了,想改就只有该父类的代码了。可惜的是,你不是父类的设计者,你是无权更改父类的代码的。

因此,选择protected还是private,这个选择还是很重要的。

  回复  引用  查看    

#4楼  2004-11-17 16:41 he [未注册用户]

派生类可以提升其父类的访问级别
-----------------------
这话说的真晦涩   回复  引用    

#5楼 [楼主] 2004-11-17 16:55 wayfarer      

public
^
internal
^
protected
^
private

这就是所谓的"提升访问级别"罗,呵呵:)   回复  引用  查看    

#6楼  2004-11-17 17:01 lichdr      

這叫cracker class,這種技巧早就再用了。
主要是用在不同的程序單元的地方。

兩個類在同一個單元就不用這麼累的。   回复  引用  查看    

#7楼  2004-11-17 17:25 Ninputer [未注册用户]

internal是没法和protected比较的,如果非要比较,那么我认为internal无法穿透程序集的边界,所以internal不如protected。

public > protected internal > protected > internal > private   回复  引用    

#8楼 [楼主] 2004-11-17 17:42 wayfarer      

在.Net Framework,确实提供了五种访问级别。不过我觉得Ninputer写的顺序似乎有误,应该是:
public > protected > internal > protected internal> private。
但是在C#中,只提供了四种,不包括protected internal。

不过对于internal和protected,没有完全的访问级别的高低界限。因为对于internal而言,只要是在同一程序集中,即使不是该类的派生类,也可以访问。而对于protected来说,另外一个程序集的类也可以访问它,但前提是必须继承该类。

所以,internal和protected两者的访问级别,以集合的概念来看,似乎是两个相交的集合。而其交集就是protected internal修饰符。它只能被同一程序集的派生类访问。   回复  引用  查看    

#9楼  2004-11-17 17:54 Ninputer [未注册用户]

不,protected internal是protected的范围 加上 internal的范围,是并集不是交集。

你好像没有用过的样子,回去试试。C#当然支持它了。VB也支持,叫Protected Friend   回复  引用    

#10楼  2004-11-17 21:12 Magicloud [未注册用户]

记得设计模式中曾提到,少用继承,多用引用,即使在对象关系上是继承的。   回复  引用    

#11楼  2004-11-17 22:32 Meyer      

internal与protected 不好比较
但protected internal 确实比他门两个的范围大,这个可以比较   回复  引用  查看    

#12楼  2004-11-18 03:20 sumtec      

敬请留意我的一篇新Blog,将对这一问题做出我个人的回答。今天太晚了,不放出来了,明天中午吧。   回复  引用  查看    

#13楼 [楼主] 2004-11-18 09:34 wayfarer      

声明的可访问性 意义
public 访问不受限制。
protected 访问仅限于包含类或从包含类派生的类型。
internal 访问仅限于当前程序集。
protected internal 访问仅限于从包含类派生的当前程序集或类型。
private 访问仅限于包含类型。

以上是MSDN对这几种访问限制的说明。Ninputer的观点是正确的,我将“当前程序集或类型”看作是“当前程序集的类型”了。protected internal 应该是internal和protected的并集,是我失误了。

不过我记得Applied .Net Framework里似乎还介绍了一种访问限制,是protected和internal的交集。这个修饰符在C#里并没有提供,但在IL里是有的,不知道是否正确,手边没有这本书,无法查阅了。   回复  引用  查看    

#14楼  2005-09-21 10:12 waj [未注册用户]

protected internal 应该是internal和protected的并集   回复  引用    

#15楼  2006-02-15 16:48 老鼠甲 [未注册用户]

考虑一个成员的访问域(Accessibility domains),应该同时考虑包含这个成员的类的访问域,一个成员实际的访问域是两者的交集   回复  引用    

#16楼  2006-02-15 22:22 Ivony... [未注册用户]

C#不支持internal protected???

事实上protected更大的作用是避免我们敲一个"."后出现一大堆我们根本就不想看到的东西。   回复  引用    

#17楼  2006-02-15 22:25 Ivony... [未注册用户]

wayfarer 还……

internal protected是internal和protected的交集。
不要老是咬文嚼字,自己试一下就全明白了。

尤其是VS2005的中文帮助,翻译错误多如牛毛……   回复  引用    

#18楼  2006-05-29 14:03 静静地坐着 [未注册用户]

并集!

FamilyOrAssembly -> protected internal
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=193386&SiteID=1   回复  引用    

#19楼  2006-07-12 17:39 sirius [未注册用户]

public > protected internal > protected > internal > private
这个顺序应该是对的

protected:只能被自身和继承的子类来访问
internal:只能被程序集内部访问,如果子类不和父类在一个程序集的话,那么子类是没有办法访问的。
protected internal:是两个的并集,无论是不是在一个程序集,子类都能访问,而且自己所在的程序集内的都能访问,说得有点乱,不过,我是理解了
^_^
  回复  引用    

#20楼  2006-07-12 17:40 sirius [未注册用户]

不过,protected和internal,应该不能简单的说谁的范围大,谁的范围小的
如果都在同一个程序集那么,自然是internal的范围大
如果子类和父类不在一个程序集的话,可能就另说了吧?应该
  回复  引用    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2004-11-17 16:32 编辑过


相关链接:
 



导航

公告

logo.gif
我的著作与译作

《软件设计精要与模式》

《WCF服务编程》

MVP_Horizontal_BlueOnly.png

From 03-03-2006
Counter: site stats

与我联系

搜索

 

常用链接

我参加的小组

我参与的团队

随笔分类(243)

随笔档案(235)

最新随笔

积分与排名

最新评论

阅读排行榜

评论排行榜