将参数中的字段传递给外部方法调用是不是违反了打开/关闭原则?

Posted

技术标签:

【中文标题】将参数中的字段传递给外部方法调用是不是违反了打开/关闭原则?【英文标题】:Does passing a field in a parameter to an external method call violate the Open/Closed principle?将参数中的字段传递给外部方法调用是否违反了打开/关闭原则? 【发布时间】:2016-04-27 19:56:11 【问题描述】:

在下面的代码中,从 class Foo 传递私有成员 _field 作为外部方法参数 (Bar.DoSomething(_field)) 是否违反了 SOLID 编程实践中的 Open/Closed principle?

在面向对象编程中,开/关原则状态 “软件实体(类、模块、函数等)应该是开放的 扩展,但关闭修改”;也就是说,这样一个 实体可以允许其行为被扩展而不修改其 源代码。

据我了解,实体应该对扩展开放,但对修改关闭。但是,在这种情况下,_fieldFoo 的构造函数中设置了一次,并且是readonly将私有成员传递给外部方法的参数是否违反了开放/封闭原则或其他一些最佳实践?

  public class Foo
  
    private readonly int _field;

    public Foo(int input)
    
      _field = input;
    

    private void FooDoSomething()
    
      Bar.BarDoSomething(_field); //Breaking Open/Closed Principle?
    
  

  public static class Bar
  
    public static void BarDoSomething(int input)
    
      //Something happens
    
  

【问题讨论】:

我建议你把这个问题转发到programmers.stackexchange.com。 @Xiaoy312 cross-posting is frowned upon @gnat 我认为 migrate 是我应该使用的词。 【参考方案1】:

不,这不违反开放/封闭原则。从Bar 的角度来看,input 不是属于Foo 的内部字段。它只是一个整数。 Foo 的内部状态仍然隐藏在类中。

更进一步,除非您在传递参数时指定ref

Bar.BarDoSomething(ref _field);

Bar 甚至不能修改_field 的值。交互是单向的。 Foo 告诉 Bar 做某事。那挺好的。

澄清一下——即使使用了ref 并且Bar 可以修改与打开/关闭原则没有任何关系的值。但是,如果Bar.DoSomething 的目的是返回一个值,那么作为一个返回int 的函数而不是修改一个值的方法会更好。这样调用者可以获取值并决定是否要更新_field

【讨论】:

我对这篇文章的解释完全不同——据我了解,任何非密封类都是开放的(用于扩展),因为它可以在不修改其源代码的情况下进行扩展(通过继承)。但是,我不确定如何解释“关闭”... 在所问问题的上下文中 - 没有以任何方式涉及行为修改,所以我会说即使非最终变量会通过引用进行修改,也不会违反原则.我是不是理解错了? 我无法从示例中得出与开放/封闭原则之间的关系,因为该示例甚至没有真正处于违反或不违反该原则的范围内。所以我只是回答,“不,它不违反它。”我可以理解为什么会出现这个问题。但即使修改了值,它也不会与该原则有任何关系。 在实践中,我将“封闭”部分理解为意味着即使派生类也隐藏了类的内部。因此,如果您从Foo 继承,那么 base 类可以修改_field,但派生类不能。因此,虽然您可以扩展它的行为,但您仍然可以将继承的类强制转换为 Foo 并相信它的行为方式完全相同。例外情况是那些打算被覆盖的方法,但您仍然想确定这些被覆盖的方法可以或不能在对象的内部状态中改变什么。 那么我们是否可以同意——如果我们是严格的——如果一个类不包含任何虚方法,它就会被关闭? (这将消除异常。)

以上是关于将参数中的字段传递给外部方法调用是不是违反了打开/关闭原则?的主要内容,如果未能解决你的问题,请参考以下文章

Java 中的值传递和参数传递

String在方法中的传递方式(调用外部方法给String变量赋值时,未得到预期结果)

为啥从 jquery 传递给控制器​​方法的参数即使不是 null 也是 null?

VB中过程调用时有几种参数传递方式,说明其区别

将属性本身传递给 C# 中的参数

Symfony3 表单组件试图将 null 传递给 PHP 7 中的类型提示方法