Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 纯写属性有实际应用吗?_Oop_Properties_Language Agnostic - Fatal编程技术网

Oop 纯写属性有实际应用吗?

Oop 纯写属性有实际应用吗?,oop,properties,language-agnostic,Oop,Properties,Language Agnostic,我不知道为什么我开始考虑这个,但现在我似乎无法停止 在C#-可能还有很多其他语言中,我记得Delphi也允许您这样做-编写以下语法是合法的: 类怪人类 { 私有void Hello(字符串名称) { WriteLine(“你好,{0}!”,name); } 公共字符串名 { 集合{Hello(name);} } } 换句话说,该属性有一个setter,但没有getter,它是只写的 我想我想不出为什么这是非法的,但我从来没有在野外看到过,我在野外看到过一些非常精彩/恐怖的代码。这似乎是一种代码

我不知道为什么我开始考虑这个,但现在我似乎无法停止

在C#-可能还有很多其他语言中,我记得Delphi也允许您这样做-编写以下语法是合法的:

类怪人类
{
私有void Hello(字符串名称)
{
WriteLine(“你好,{0}!”,name);
}
公共字符串名
{
集合{Hello(name);}
}
}
换句话说,该属性有一个setter,但没有getter,它是只写的

我想我想不出为什么这是非法的,但我从来没有在野外看到过,我在野外看到过一些非常精彩/恐怖的代码。这似乎是一种代码气味;似乎编译器应该给我一个警告:

CS83417:属性“Name”似乎完全无用且愚蠢。糟糕的程序员!考虑用方法替换。< /P> 但也许我做这件事的时间还不够长,或者在一个太窄的领域里工作,看不到任何有效使用这种结构的例子


是否存在仅写属性的实际示例,它们要么不能被直接的方法调用替换,要么会变得不那么直观?

仅写属性实际上非常有用,我经常使用它们。这都是关于--限制对对象组件的访问。您通常需要为需要在内部使用的类提供一个或多个组件,但没有理由让其他类可以访问这些组件。这样做只会使您的类更加混乱(“我是使用这个getter还是这个方法?”),而且您的类更有可能被篡改或绕过其真正用途


有关这方面的有趣讨论,请参阅。我并不像这篇文章的作者那样对这件事很坚决,但我认为这是一件值得思考的事情。我通常使用Setter,但很少使用getter。

从技术上讲,仅Setter属性本身并没有什么问题。Setter可以进行一些验证,也许其他一些方法(public或private)也可以依赖它

例如:

class-SomeClass{
私有int_someVar;
SomeClass(int-someVar){
如果(someVar>0)\u someVar=someVar;
}
公共int-SomeVar{
设置{if(value>0)\u someVar=value;}
}
公共字符串函数(){
return“这是一个使用_someVar”+_someVar的重要函数;
}
}

因此,声明本身可能合法有效。虽然你的方法体是一个巨大的代码气味,但这不是编译器要关心的工作。

我对这个问题的第一反应是:“方法呢?”


我认为只写属性在几种情况下都很有用。例如,当您不想公开内部表示(封装)时,同时允许更改对象的状态。JavaUTI.RAPID是一个很好的例子。

< P>不,我可以想象任何情况下它们都不能被替换,尽管可能有人认为它们更可读。 假设情况:

CommunicationDevice.Response=“你好,世界”
而不是

CommunicationDevice.SendResponse(“你好,世界”)
主要工作是执行IO副作用或验证

有趣的是,VB.NET甚至为这种奇怪的属性设置了自己的关键字;)

Public WriteOnly属性Foo()为整数
设置(值为整数)
' ... '
端集
端属性
尽管来自外部的许多“只写”属性实际上都有一个私有getter。

代码分析(又称FxCop)确实为您提供了一个诊断:

:Microsoft。设计:因为 属性'WeirdClass.Name'是只写的, 添加一个具有 大于或等于的可访问性 等于其setter或将其转换为 属性转换为方法


就我而言,他们没有。每次我使用一个只写属性作为快速攻击,我后来都会后悔。通常我会得到一个构造函数或一个完整的属性


当然,我想证明一个否定的观点,所以也许我遗漏了一些东西

在XNA项目中,我有类似于以下内容的代码。正如您所看到的,Scale是只写的,它很有用并且(合理地)直观,而读取属性(get)对它来说没有意义。当然可以用方法替换它,但我喜欢它的语法

公共类MyGraphicalObject
{
公共双ScaleX{get;set;}
公共双尺度{get;set;}
公共双尺度{get;set;}
公共双刻度{set{ScaleX=ScaleY=ScaleZ=value;}
//更多。。。
}

当你不应该读你写的东西时,只写东西是有用的

例如,在屏幕上绘图时(这正是桌面窗口管理器在Windows中所做的):
你当然可以在屏幕上画图,但是你永远不需要读回数据(更不用说期望得到和以前一样的设计了)

现在,只写属性是否有用(与方法相反),我不确定它们的使用频率。我想您可以想象一种具有“BackgroundColor”属性的情况,在这种情况下,向其写入设置屏幕的背景色,但读取没有意义(必要)。

所以我不确定这一部分,但总的来说,我只想指出,在某些情况下,您只写数据,而从不读取数据。

只写属性的一个用途是支持setter依赖项注入,这通常用于可选参数

假设我上过一节课:

public class WhizbangService {
    public WhizbangProvider Provider { set; private get; }
}
WhizbangProvider不打算被外部世界访问。我从来不想与
服务提供商进行交互,因为它太复杂了。我需要一门像惠兹班斯这样的课
service.Provider = new FireworksShow();
service.Start();
service.Stop();
service.Provider = new FountainDisplay(new StringOfLights(), 20, UnitOfTime.Seconds);
service.Start();
public abstract class DisplayService {
    public WhizbangProvider Provider { set; private get; }
}

public class WhizbangService : DisplayService  { }
public abstract class DisplayService {
    public WhizbangProvider Provider;

    protected DisplayService(WhizbangProvider provider) {
       Provider = provider ?? new DefaultProvider();
    }
}

public class WhizbangService : DisplayService  { 
    public WhizbangService(WhizbangProvider provider) 
      : base(provider) 
    { }
}
public AllowedAttribute: AuthorizeAttribute
{
    public AllowedAttribute(IStore store) {...}
    private IStore Store { get; set; }
    ...
}
public AllowedAttribute: AuthorizeAttribute
{
    [Inject] public IStore Store { private get; set; }
    ...
}
public int MyFancyWepapiMethod([FromBody]CallParams p) {
    return p.MyIntPropertyForAjax.HasValue ? p.MyIntPropertyForAjax.Value : 42;
}

public class CallParams
{
    public int? MyIntPropertyForAjax;

    public object TryMyIntPropertyForAjax
    {
        set
        {
            try { MyIntPropertyForAjax = Convert.ToInt32(value); }
            catch { MyIntPropertyForAjax = null; }
        }
    }
}
var callparameter = {
    TryMyIntPropertyForAjax = 23
}
public partial class ShowMeTheTime : Page, ICurrentTimeView
{
    protected void Page_Load(object sender, EventArgs e) 
    {
        CurrentTimePresenter presenter = new CurrentTimePresenter(this);
        presenter.InitView();
    }

    public DateTime CurrentTime 
    {
        set { lblCurrentTime.Text = value.ToString(); }
    }
}
public void InitView() 
{
    view.CurrentTime = DateTime.Now;
}