Java 中“私有静态最终”和“公共静态最终”类变量的最接近的 Ruby 表示形式?

2024-03-06

给定下面的 Java 代码,您可以最接近地表示这两个static finalRuby 类中的变量?并且,在 Ruby 中是否可以区分private static and public staticJava 中的变量?

public class DeviceController
{
  ...
  private static final Device myPrivateDevice = Device.getDevice("mydevice");
  public static final Device myPublicDevice = Device.getDevice("mydevice");
  ...
  public static void main(String args[])
  {
   ...
  }
}

Ruby 中确实没有等效的构造。

然而,看起来您正在犯一个经典的移植错误:您有一个solution并尝试将其翻译成语言 B,而你真正应该做的是弄清楚problem然后想办法用B语言解决这个问题。

我无法确定您要从那个小代码片段中解决的问题是什么,但这是one如何在 Ruby 中实现它的可能想法:

class DeviceController
  class << self
    def my_public_device;  @my_public_device  ||= Device['mydevice'] end

    private

    def my_private_device; @my_private_device ||= Device['mydevice'] end
  end
end

这是另一个:

class DeviceController
  @my_public_device  ||= Device['mydevice']
  @my_private_device ||= Device['mydevice']

  class << self
    attr_reader :my_public_device, :my_private_device
    private :my_private_device
  end
end

(区别在于,第一个示例是惰性的,它仅在第一次调用相应的属性读取器时初始化实例变量。第二个示例在类体执行后立即初始化它们,即使它们从不需要,就像Java 版本可以。)

让我们回顾一下这里的一些概念。

在 Ruby 中,就像在所有其他“适当的”(对于“适当的”的各种定义)面向对象语言中一样,状态(实例变量、字段、属性、槽、属性,无论你想如何称呼它们)都是always私人的。有no way从外部访问它们。与对象通信的唯一方法是向其发送消息。

[注:每当我写“没办法”、“总是”、“唯一的办法”等之类的东西时,它实际上并不意味着“没有办法,除了反思”。在这种特殊情况下,有Object#instance_variable_set, 例如。]

换句话说:在 Ruby 中,变量始终是私有的,访问它们的唯一方法是通过 getter 和/或 setter 方法,或者如 Ruby 中所称,属性读取器和/或写入器。

现在,我继续写关于实例变量,但在 Java 示例中我们有静态字段, i.e. class变量。嗯,在 Ruby 中,与 Java 不同,类也是对象。他们是Class类等等,就像任何其他对象一样,它们可以有实例变量。因此,在 Ruby 中,类变量的等价物实际上只是一个标准实例变量,它属于一个恰好是类的对象。

(还有类层次结构变量,用双 at 符号表示@@sigil。这些真的很奇怪,你应该忽略它们。类层次结构变量在整个类层次结构中共享,即它们所属的类、其所有子类及其子类及其子类……以及所有这些类的所有实例。实际上,它们更像是全局变量而不是类变量。他们真的应该被称为$$var代替@@var,因为它们与全局变量的关系比实例变量更密切。它们并非完全无用,只是很少有用。)

所以,我们已经介绍了“字段”部分(Java 字段== Ruby 实例变量),我们已经介绍了“公共”和“私有”部分(在 Ruby 中,实例变量始终是私有的,如果你想将它们设为公共,使用公共 getter/setter 方法)并且我们已经介绍了“静态”部分(Java 静态字段 == Ruby 类实例变量)。那么“最后”部分呢?

在 Java 中,“final”只是“const”的一种有趣的拼写方式,设计者避免使用这种方式,因为constC 和 C++ 等语言中的关键字被巧妙地破坏了,他们不想让人们感到困惑。红宝石does有常量(以大写字母开头表示)。不幸的是,它们并不是真正恒定的,因为尝试修改它们,同时生成警告,实际上是有效的。因此,它们更多的是一种约定,而不是编译器强制执行的规则。然而,常量更重要的限制是它们始终是公共的。

所以,常量几乎是完美的:它们不能被修改(嗯,它们不应该被修改),即它们是final,它们属于一个类(或模块),即它们是static。但他们总是public,所以不幸的是它们不能用于建模private static final fields.

这正是思考问题而不是解决方案的关键所在。你想要什么?你想要说明的是

  1. 属于一个类,
  2. 只能读不能写,
  3. 仅初始化一次并且
  4. 可以是私有的或公共的。

您可以实现所有这些,但方式与 Java 完全不同:

  1. 类实例变量
  2. 不提供setter方法,只提供getter方法
  3. 使用 Ruby 的||=复合赋值仅赋值一次
  4. 获取方法

您唯一需要担心的是,您没有分配给@my_public_device任何地方,或者更好的是,根本不访问它。始终使用 getter 方法。

是的,这个is实施中存在漏洞。 Ruby 通常被称为“成年人的语言”或“成年人同意的语言”,这意味着您不必让编译器强制执行某些事情,而只需将它们放入文档中,并简单地相信您的开发人员同伴已经学会了接触其他内容人的私处是很粗鲁的...


完全是一个不同的保护隐私的方法是函数式语言中使用的方法:使用闭包。闭包是关闭其词法环境的代码块,即使在该词法环境超出范围之后也是如此。这种实现私有状态的方法在Scheme中非常流行,但最近也被Douglas Crockford等人推广。对于 JavaScript。下面是 Ruby 中的一个示例:

class DeviceController
  class << self
    my_public_device, my_private_device = Device['mydevice'], Device['mydevice']

    define_method :my_public_device  do my_public_device  end
    define_method :my_private_device do my_private_device end

    private :my_private_device
  end # <- here the variables fall out of scope and can never be accessed again
end

请注意我的答案顶部的版本之间微妙但重要的区别:缺乏@印记。在这里,我们正在创造local变量,不instance变量。一旦类主体结束,这些局部变量就会超出范围,并且永远无法再次访问。Only定义两个 getter 方法的两个块仍然可以访问它们,因为它们关闭了类主体。现在,他们是really私人的and他们是final,因为整个程序中唯一仍然可以访问它们的是纯getter method.

这可能不是 Ruby 惯用的做法,但对于任何有 Lisp 或 JavaScript 背景的人来说都应该足够清楚了。它也非常优雅。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 中“私有静态最终”和“公共静态最终”类变量的最接近的 Ruby 表示形式? 的相关文章

随机推荐

  • 如何启用/禁用 JEditable

    SOLUTION 感谢 Arman 的 P 概念验证 终于让它可以与我的网站一起使用了 CODE Edit Note function function makeEditable edit editable ajax save php ed
  • CStr() 与 Str() 与 .ToString()

    我想知道两者之间到底有什么区别CStr Str and ToString Label1 Text CStr Int Rnd 10 and Label1 Text Str Int Rnd 10 and Label1 Text Int Rnd
  • 以编程方式将主题应用到按钮

    是否可以以编程方式将 Widget AppCompat Button 主题应用于按钮 Button button new Button context button setText Button 目前 我正在使用自定义可绘制资源 尝试实现类
  • 如何从GridView中删除一行?

    我在用GridView控制在asp net questions tagged asp net 2005 c questions tagged c 23 using 如何从中删除特定行GridView 我编写了以下代码 但这不起作用 Data
  • 退出应用程序会导致错误“来自调试器的消息:由于信号 9 而终止”

    我正在编写一个基本的音乐播放器应用程序 但在处理应用程序状态转换时遇到一些问题 我正在使用 Swift 3 和 MPMusicPlayerController systemMusicPlayer 目标是这样的 1 当用户点击主页按钮并且应用
  • 使用 Sass 以可重用的方式设计一组特定的输入类型

    我想要一个 mixin 函数 它返回 HTML5 输入类型的列表 我想在一个地方管理它 当新类型出现时 改变函数 而不是代码中其他地方的所有地方 问题似乎是 mixins 的设计目的不是返回可以在 CSS 花括号之外使用的字符串 这是我的
  • jQuery 热键 - 解除绑定?

    我有一个 jQuery 对话框 它初始化热键如下 循环从 1 到 9 问题是 如果您关闭对话框然后重新打开对话框 它不断重新绑定 因此当您按下 1 键时 它会运行两次 三次 四次等 它会不断增长 我尝试杀死对话框上的键绑定关闭 docume
  • 带参数和选项的 C# 方法重载

    今天我发现了一些奇怪的事情 我想知道为什么这有效 static void Main string args Console WriteLine ExampleMethod 3 Console ReadKey public static st
  • 无反向匹配 /

    我正在尝试制作非常有意义的网址 但我想我做错了 这有效 from django conf urls defaults import patterns url from places views import explore view url
  • 如何仅在本地标头上运行预处理器?

    我希望预处理器读取本地标头的包含内容 但忽略系统标头的包含内容 换句话说 如何让预处理器跳过以下形式的预处理指令 include
  • 如何通过 Fluent NHibernate 添加事件监听器?

    我想添加一个事件监听器 IPreUpdateEventListener 添加 NHibernate 但我似乎找不到使用流畅配置的示例 我希望能够在创建会话工厂时添加监听器 例如当执行以下代码时 sessionFactory Fluently
  • phpMyAdmin 提供了export.php 而不是数据库sql 转储

    环境 Windows 10 Enterprise x64 上的 Wamp 服务器 2 5 x64 MySQL 5 6 17 phpmyadmin4 1 14 全新安装 自昨天完全安装以来没有重大变化 完全控制访问C wamp tmp Win
  • VS Code 中的 Prettier - 在双引号内设置双引号的格式

    我在 VS Code 中使用 Prettier 扩展 我想在代码中使用双引号 jsxSingleQuote 和 singleQuote 设置为 false 当我在这行代码上运行 format 时 var hello hello Pretti
  • 更改 AppSetting 不会对应用程序产生影响

    在我正在 ASP Net 上开发的应用程序之一中 在此应用程序中 我们使用了大量的 AppSettings 在最初的开发中我们使用了ConfigurationManager AppSettings 但随着开发的进展 我们创建了一个实用程序类
  • 正向地理编码后如何返回坐标?

    我试图查看用户是否在某个地址的一定距离内 我已成功获取用户位置 并使用正向地理编码转换地址 我留下了两组坐标 我试图做出一个 if 语句 表示如果它们在 一定距离 内 则打印一些内容 目前 当我打印地标函数内的坐标时 我得到了所需的坐标 当
  • 是否有一个类来保存文件系统路径?

    在 NET 基类库中 有一个 System IO Path 类 用于对表示文件系统路径的字符串执行常见操作 然而 我需要的是封装路径的类相反 我得到了类型安全和可能更短的路径操作表示法 我正在考虑 NET 等价的C Boost 的 http
  • Android 蓝牙跨平台互操作性

    我有一个在 Windows 机器上为 Net 编程的蓝牙服务 我希望我的 Android 2 1 手机能够连接到它 服务器正在侦听 Android 用于连接的相同 UUID 但连接失败 当我尝试连接到未侦听该 UUID 的设备时 出现异常并
  • 无法两次更改复选框视图的背景颜色 - Android

    我尝试改变CheckBox用户将其状态更改为后的背景Checked 下面的代码不能很好地工作 如果我单击未选中的复选框 它将状态和颜色更改为蓝色 当我再次单击它并取消选中时 颜色保持蓝色而不是更改为红色 我做了介绍电话无效 没有成功 我确认
  • 如果 gulp 安装在与 gulpfile.js 不同的文件夹中(node_modules),如何运行 gulp

    我在一个目录中有 gulpfile js 在另一个目录中有 node modules 当我运行 gulp 时 出现错误 在 目录 中找不到本地gulp 尝试运行 npm install gulp 问题是 我无法在 gulpfile js 目
  • Java 中“私有静态最终”和“公共静态最终”类变量的最接近的 Ruby 表示形式?

    给定下面的 Java 代码 您可以最接近地表示这两个static finalRuby 类中的变量 并且 在 Ruby 中是否可以区分private static and public staticJava 中的变量 public class