我是以下课程:
public class Humptydump
{
public Humptydump()
{ }
public Rectangle Rectangle { public get; private set; }
}
在这个类中,Rectangle类来自system.drawing,
我如何制作它让人们无法访问矩形的方法,但可以获得矩形本身?
答案 0 :(得分:3)
在你的情况下,它将“正常工作”。
由于Rectangle
是struct
,您的媒体资源将返回Rectangle
的副本。因此,任何人都不可能直接修改Rectangle
,除非您公开允许此方法。
话虽这么说,一般来说,提供对类型的访问是不可能的,而不提供对类型上定义的方法的访问。方法与类型一致。在这些情况下,唯一的选择是创建一个新类型,在没有您希望公开的数据或方法的情况下公开您选择的数据,并提供对它的访问。
答案 1 :(得分:0)
如果矩形不是一个结构体,那么可能会导出它并隐藏这些方法:
public class DerivedClass : BaseClass
{
new private SomeReturnType SomeMethodFromBaseClasse(SameParametersAsInBaseClassAndSameSignature
{
//this simply hides the method from the user
//but user will still have the chance to cast to the BaseClass and
//access the methods from there
}
}
答案 2 :(得分:0)
您是在具体谈论Rectangle
对象,还是在更通用的术语上,只是以此为例?
如果你正在谈论一个更通用的术语,那么在重构模式中经常会出现这种情况。这通常发生在对象上的集合中。例如,如果您公开List<T>
,那么即使设置者是私有的,人们仍然可以通过getter修改集合,因为他们实际上并不是设置集合如此。
要解决此问题,请考虑Law of Demeter。也就是说,当有人与对象公开的集合进行交互时,他们真的是否正在与对象本身进行交互?如果是这样,则不应该公开该集合,而是该对象应该公开它所需的功能。
所以,在集合的情况下,你可能会得到这样的结果:
class SomeObject
{
private List<AnotherObject> Things;
public void AddAnotherObject(AnotherObject obj)
{
// Add it to the list
}
public void RemoveAnotherObject(AnotherObject obj)
{
// Remove it from the list
}
}
当然,您可能还希望公开对象本身的一些副本供人们阅读,但不能修改。对于一个集合,我可能会这样做:
public IEnumerable<AnotherObject> TheObjects
{
get { return Things; }
}
这样任何人都可以看到对象的当前状态并枚举它们,但它们实际上无法修改它。不是因为它没有setter,而是因为IEnumerable<T>
接口没有修改枚举的选项。只能枚举它。
对于Rectangle
的情况(或类似的东西,不管怎样都不是通过值传递的结构),你会做一些非常相似的事情。存储私有对象并提供公共功能以通过类本身对其进行修改(因为我们所讨论的是类需要知道其成员何时被修改)以及检查它的功能而无法修改正在进行的操作检查。这样的事情,也许是:
class SomeObject
{
private AnotherObject Thing;
public AnotherObject TheThing
{
get { return Thing.Copy(); }
}
public void RenameThing(string name)
{
Thing.Name = name;
}
// etc.
}
在这种情况下,如果没有详细了解AnotherObject
是什么(所以在某些方面考虑伪代码),检查内部对象的属性会返回它的副本,而不是实际的引用到实际的对象。对于值类型,这是该语言的默认行为。对于参考类型,您可能需要在此与性能之间取得平衡(如果创建副本是一项繁重的操作)。
在这种情况下,您还需要注意使对象的界面不直观。使用代码可能希望能够修改被检查的内部对象,因为它公开了修改自身的功能。事实上,他们可以修改他们拥有的副本。你如何解决这个问题在很大程度上取决于对象的概念性质以及它们之间的相互关系,这是一个人为的例子并没有真正传达出来的。您可以创建一个自定义DTO(甚至是一个结构),它只返回内部对象的可观察属性,这使得它更复杂,而不是原始对象。您可能只是说它是intellisense评论中的副本。您可以创建单独的属性以返回内部对象的单个数据元素而不是单个属性以返回对象本身。有很多选项,由您决定什么对您的对象最有意义。