lua的私有性(privacy)

简介:   很多人认为私有性是面向对象语言的应有的一部分。每个对象的状态应该是这个对象自己的事情。在一些面向对象的语言中,比如C++和Java你可以控制对象成员变量或者成员方法是否私有。其他一些语言比如Smalltalk中,所有的成员变量都是私有,所有的成员方法都是公有的。
  很多人认为私有性是面向对象语言的应有的一部分。每个对象的状态应该是这个对象自己的事情。在一些面向对象的语言中,比如C++和Java你可以控制对象成员变量或者成员方法是否私有。其他一些语言比如Smalltalk中,所有的成员变量都是私有,所有的成员方法都是公有的。第一个面向对象语言Simula不提供任何保护成员机制。
  如前面我们所看到的Lua中的主要对象设计不提供私有性访问机制。部分原因因为这是我们使用通用数据结构tables来表示对象的结果。但是这也反映了后来的Lua的设计思想。Lua没有打算被用来进行大型的程序设计,相反,Lua目标定于小型到中型的程序设计,通常是作为大型系统的一部分。典型的,被一个或者很少几个程序员开发,甚至被非程序员使用。所以,Lua避免太冗余和太多的人为限制。如果你不想访问一个对象内的一些东西就不要访问(If you do not want to access something inside an object, just do not do it.)。
  然而,Lua的另一个目标是灵活性,提供程序员元机制(meta-mechanisms),通过他你可以实现很多不同的机制。虽然Lua中基本的面向对象设计并不提供私有性访问的机制,我们可以用不同的方式来实现他。虽然这种实现并不常用,但知道他也是有益的,不仅因为它展示了Lua的 一些有趣的角落,也因为它可能是某些问题的很好地解决方案。设计的基本思想是,每个对象用两个表来表示:一个描述状态;另一个描述操作(或者叫接口)。对 象本身通过第二个表来访问,也就是说,通过接口来访问对象。为了避免未授权的访问,表示状态的表中不涉及到操作;表示操作的表也不涉及到状态,取而代之的 是,状态被保存在方法的闭包内。例如,用这种设计表述我们的银行账号,我们使用下面的函数工厂创建新的对象:
function newAccount (initialBalance)
    local self = { balance = initialBalance }
    local withdraw = function (v)
       self.balance = self.balance - v
    end

    local deposit = function (v)
       self.balance = self.balance + v
    end

    local getBalance = function () 
        return self.balance 
    end
    
    return {
       withdraw = withdraw,
       deposit = deposit,
       getBalance = getBalance
    }
end

acc1 = newAccount(100.00)
acc1.withdraw(40.00)

print(acc1.getBalance())   -- 60
acc1.deposit(40)
print(acc1.getBalance())   -- 100

print(acc1.balance)        -- nil

  首先,函数创建一个表用来描述对象的内部状态,并保存在局部变量self内。然后,函数为对象的每一个方法创建闭包(也就是说,嵌套的函数实例)。最后,函数创建并返回外部对象,外部对象中将局部方法名指向最终要实现的方法。这儿的关键点在于:这些方法没有使用额外的参数self,代替的是直接访问self。因为没有这个额外的参数,我们不能使用冒号语法来访问这些对象。函数只能像其他函数一样调用:   acc1.deposit(40)     acc1.getBalance()

  这种设计实现了任何存储在self表中的部分都是私有的,newAccount返回之后,没有什么方法可以直接访问对象,我们只能通过newAccount中定义的函数来访问他。虽然我们的例子中仅仅将一个变量放到私有表中,但是我们可以将对象的任何的部分放到私有表中。我们也可以定义私有方法,他们看起来象公有的,但我们并不将其放到接口中。例如,我们的账号可以给某些用户取款享有额外的10%的存款上限,但是我们不想用户直接访问这种计算的详细信息,我们实现如下:

 1 function newAccount (initialBalance)
 2     local self = { balance = initialBalance , 
 3                    LIM = 1314 }
 4 
 5     local withdraw = function (v)
 6        self.balance = self.balance - v
 7     end
 8 
 9     local extra = function ()
10        if self.balance > self.LIM then
11            return self.balance*0.10
12        else
13            return 0
14        end
15     end
16 
17     local deposit = function (v)
18        self.balance = self.balance + v
19     end
20 
21     local getBalance = function () 
22         return self.balance + extra()  --[此处非self.extra()]
23     end
24     
25     return {
26        withdraw = withdraw,
27        deposit = deposit,
28        getBalance = getBalance,
29        -- extra = extra,
30     }
31 end

       这样,对于用户而言就没有办法直接访问extra函数了;如此 也就实现lua private function。

      使用table来实现面向对象的编程方式,几乎可以实现所有面向对象的编程特性
    但它没有也不想去实现的就是对象的私密性,也就是c++里的private、public、protected
    这与lua设计的初衷有关,lua定位于小型的程序开发,参与一个工程的人不会很多,自行约束
    非要实现私密性的话lua也不是不能,只是不能再使用table和元表的方式了
 
      它可以通过如上述所写方方式实现,在闭包里定义一个table的upvalue,然后把所有闭包函数都定义在这里table里,
    然后返回这个table,用key访问内部方法
      使用闭包实现对象的方式比用table效率高并实现了绝对的私密性,但无法实现继承,相当于简单的小对象
    甚至可以在闭包里仅定义一个方法,然后通过key来判断调用是什么方法
      Tcl/Tk对它的窗口部件就使用这种方法

原文出自: (Here)   参考 Here

倾城之链 | NICE LINKS DJI Mavic Air
目录
相关文章
|
自然语言处理 安全 算法
开源与闭源:创新与安全的平衡
开源与闭源:创新与安全的平衡
359 0
|
JSON 数据格式
【异常】com.alibaba.fastjson.JSONException: unclosed string : U
【异常】com.alibaba.fastjson.JSONException: unclosed string : U
2582 0
|
6月前
|
敏捷开发 数据可视化 Devops
接口状态自由定制!Apipost、 Apifox和Postman:谁在拖垮你的开发效率
在DevOps盛行的今天,许多团队的接口管理仍停留在传统模式,导致需求延期率飙升34%(Gartner 2023数据)。看似标准的流程可能成为效率杀手,尤其在紧急插入状态时问题凸显。企业级接口管理需满足多环境适配、角色权限隔离、自定义工作流及可视化看板四大需求。对比Apifox、Postman与Apipost三大工具,Apipost以其灵活的状态工厂模式和智能流转规则脱颖而出,支持定制化状态链并自动触发相关操作,助力车联网等企业提升200%协作效率。告别Excel手动维护,开启接口管理新纪元。
|
10月前
|
存储 Java 编译器
Java泛型类型擦除以及类型擦除带来的问题
泛型擦除是指Java编译器在编译期间会移除所有泛型信息,使所有泛型类型在运行时都变为原始类型。例如,`List<String>` 和 `List<Integer>` 在JVM中都视为 `List`。因此,通过 `getClass()` 比较两个不同泛型类型的 `ArrayList` 实例会返回 `true`。此外,通过反射调用 `add` 方法可以向 `ArrayList<Integer>` 中添加字符串,进一步证明了泛型信息在运行时被擦除。
202 2
|
10月前
|
存储 安全 Java
如何避免 Java 中的“ArrayStoreException”异常
在Java中,ArrayStoreException异常通常发生在尝试将不兼容的对象存储到泛型数组中时。为了避免这种异常,确保在操作数组时遵循以下几点:1. 使用泛型确保类型安全;2. 避免生类型(raw types)的使用;3. 在添加元素前进行类型检查。通过这些方法,可以有效防止 ArrayStoreException 的发生。
179 3
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的度假村管理系统设附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的度假村管理系统设附带文章源码部署视频讲解等
83 0
|
开发框架 Java .NET
Mono 现状与未来: 从 Xamarin 到 WebAssembly、Blazor 及.NET 5
  本文要点:   Mono 项目始于 2001 年,是首个面向.NET 应用程序的多平台、开源框架的项目。Xamarin 和 Blazor 分别代表了微软在移动和 Web 应用程序方面的努力,它们都是基于 Mono 并由 Mono 提供支持的。.NET 5 为用户提供了两种运行时选项:高性能的 CoreCLR(用于服务器和桌面应用程序)和轻量级的 Mono(用于移动设备和 WebAssembly)。尽管 Mono 已经是.NET 的一部分了,但仍有一些开发工作要致力于改善 Mono 的运行时性能和垃圾回收器。现在.NET Core 可以与 Mono 并行安装了,因此可以一起演进语言和运行时
1394 0
|
存储 人工智能 缓存
企业应该如何上云?阿里云企业上云场景化解决方案
企业应该如何上云?应该选择那些阿里云产品?阿里云为企业用户推出6大企业上云场景化解决方案,具体方案有企业初创场景解决方案、跨境电商解决方案、企业管理系统云上部署解决方案、企业建站场景解决方案、高并发云上架构解决方案和Web与移动App云上部署解决方案,下面是方案主要内容概述。
656 0
企业应该如何上云?阿里云企业上云场景化解决方案
|
Kubernetes 容器 Perl
应用在k8s上运行的几种网络模式
应用部署在k8s上,首先想到的是应用k8s的默认service模式配置。 应用通过service向集群内部(ClusterIP)和集群外部(NodePort)暴露服务。k8s中的其他应用通过kube-dns提供的dns解析功能,访问servicename:port即可访问service后面的pod的服务。
4130 0
|
Shell Linux 数据格式