Self
Self语言，是一种基于原型的面向对象的程序设计语言，也是一个集成开发环境和运行环境，由David Ungar和Randy Smith最初在1986年于施乐帕罗奥多研究中心设计。Self语言在Smalltalk的基础上，去除了变量从而彻底体现了一切都是对象的风格。在实现Self系统的过程中，设计研究人员发展出了一种动态自适应编译技术。
Self语言把在概念上精简Smalltalk作为设计原则。它在把消息作为最基本的操作的同时，取消了类的概念，只有对象的概念。它把对象的特性，理解为获取或更改特性的这两种方法，从而把特性的概念简化为方法，即取消了变量及其赋值，并以通过消息来读槽和写槽的方式来取代之。Self提出了特质的概念，用实现了。
尽管Self系统一次运行在一个进程中，但实际上可以分成两个部分：Self虚拟机和Self世界（Self world）。Self世界是一个Self对象库，Self对象包括数据对象和方法对象，方法对象的代码部分，是用一种指令非常简单的字节码（bytecode）表示的，字节码由Self虚拟机来解释。当Self程序从终端、文件或者图形用户界面输入到系统之中时，Self系统把源程序解析转化为Self世界里的对象。
动态自适应编译技术的采用，提高了Self代码的执行效率。对经常执行的方法，虚拟机将进一步把字节码转化为本机代码。Self虚拟机还提供了一些可供调用的，用来实现算术运算、对象复制、输入输出等。
Self也拥有一个图形用户界面Morphic，Self的编程环境，也是基于Morphic来实现的。Self在精简语言概念的同时，也把大量的工作转交给环境来处理，语言中的反射机制也同环境密切相关。
在1986年，David Ungar和Randy Smith在施乐帕罗奥多研究中心，提出了Self语言的最初设计，并在1987年的OOPSLA'87的论文《Self：简单性的能力》中给出了描述，此文在2006年被评为1986年到1996年间三个最有影响的OOPSLA论文之一。
1987年初，Craig Chambers、Elgin Lee和Martin Rinard在Smalltalk上给出了Self的第一个实验性解释器。1987年夏，Self项目在斯坦福大学正式开始，1988年夏给出了第一个有效率的实现，并发布了1.0和1.1两个版本。1991年初，Self项目移至Sun微系统，并且在1992年发布了2.0版。1993年1月，Self 3.0版发布。
1995年7月，Self 4.0版发布。在这个版本中包括了一个全新的图形用户环境Morphic。在2016年发行了4.3版本并可运行在Mac OS X和Solaris上。在2010年发行了版本4.4，由最初团队的某些人和独立编程者形成的小组开发，它和所有后续版本可以运行在Mac OS X和Linux上。2014年1月发行了4.5版本。2017年5月发行了版本2017.1。
Self的发展基本已经停滞，但在发展Self过程中探索出的一些技术，在其他的系统中得到了应用。在Self的实现中采用的各种编译优化技术，直接导致了Java Hotspot虚拟机的产生；在Smalltalk的一个实现Squeak中，采用了Self图形用户界面Morphic的设计方案，放弃了Smalltalk-80中采用的MVC的方案。Self是对JavaScript编程语言设计有最主要影响者之一。
传统的基于类的面向对象语言，基于了根深蒂固的二元性：
例如，假设类codice_1（车辆）的对象有一个“名字”，和进行各种动作的能力，比如“开车上班”和“运送建材”。codice_2是类codice_1的特定对象（实例），它的“名字”是“Bob's car”。在理论上，你可以向codice_2发送消息，告诉它去“运送建材”。
这个例子展示了这种方式的一个问题：codice_2，恰巧是一个运动车，（在任何意义上）不能装载和运送建材，但这是建模codice_1所必须拥有的能力。通过使用子类来建立特殊化的codice_1，可产生一个更有用的模型；例如codice_8（运动车）和codice_9（平板卡车）。只有类codice_9的对象需要提供“运送建材”的机能；运动车，不适合这种工作，它只需要“快速行驶”。但是，这种深入建模在设计期间，需要更多的洞察力，洞察那些可能只在引起了问题时才显现出的事情。
这个问题是在原型（prototype）这个概念背后的动机因素之一。除非你能必然性的预测出一组对象和类，在遥远未来时所要有的品质，你不能恰当的设计好一个类的层级。程序最终需要增加行为，实在是太频繁了，而系统的很多节段将需要重新设计（或重新构建），来以不同的方式迸发出对象。早期的面向对象语言如Smalltalk的实验，显示出这种问题反反复复的出现。系统趋向于增长到一定程度后，就变得非常僵化，因为在编程者的代码下的深层的基本类，逐渐成为一个简单的“错误”。 没有变更起初的类的容易方式，严重的问题就会出现。
动态语言如Smalltalk，允许通过周知的按照类的方法进行这种变更；即通过改变类，基于它的对象就可以改变它们的行为。但是，进行这种变更必须非常小心，因为基于相同类的其他对象，可能把它当作“错误行为”：“错误”经常是依赖于场景的。这是问题的一种形式。进一步的说，在语言如C++中，这里的子类可以从超类分别的编译，对超类的变更实际上可以破坏预编译的子类方法。这是脆弱基类问题的另一种形式，也是的一种形式。
在Self和其他基于原型的编程语言中，消除了在类和对象之间的这种二元性。
不再有基于某种“类”的一个对象“实例”，在Self中，你可以复制一个现存的对象，并改变它。所以codice_2可以通过制作现存的codice_1对象的副本来建立，并增加“快速行驶”方法，建模它恰好是一辆保时捷911的事实。主要用来制作副本的基本对象叫做“原型”。这种技术被称为是一种非常简化的机制。如果一个现存的对象（或对象的集合）被证明是个不适当的模型，编程者可以简单的建立有正确行为的一个修改的对象，并转而使用它。使用现存对象的代码不会改变。
下面简要描述Self语言的语法和语义。
（literal）包括：数、用codice_13包围起来的字符串对象，块和一般的对象。对象文字用圆括号来界定。在圆括号内，对象描述构成自竖杠codice_14界定的槽的一个列表，随后是在这个对象被求值时要执行的代码。例如：
槽（slot）是名字-值对，槽包含到其他对象的引用。槽描述符有两种：codice_15，指示将这个读/写槽初始化为求值表达式的结果，这个槽对应于其他语言中的读写变量；codice_16，指示将这个只读槽初始化为求值表达式的结果。假如codice_17对象中有个叫做codice_18的槽，则，返回在槽codice_18中的值；而，设置槽codice_18的值为codice_21。
任何槽都可以通过增加星号后缀，来制成父槽。星号不是槽名字的一部份，在将名字与消息进行匹配时候忽略它。例如一个初始化了的可变的点可以定义为：
( | parent* = traits point.
一个真正的空对象指示为codice_22或简单的codice_23，它根本不接收任何消息。
方法（method）是除了参数槽和/或局部槽之外，还包含代码的对象。参数（argument）槽名字开始于一个冒号，它不是槽名字的一部分，在将名字与消息进行匹配时候忽略它。参数槽总是只读的，并且不能对它们指定初始化者。下面例子是计算平方的方法对象：
一个正常的方法是不嵌入到其他代码之中的方法，它总是有一个叫做codice_24的隐含的父参数槽。方法只能存放在只读槽中。
如果一个槽包含一个方法，在求值这个槽来响应发来的消息的时候，这个方法对象被（clone），从而新建它的一个活动（activation）对象，它包含这个方法的参数槽和局部槽；复制者的codice_24父槽，初始化为这个消息的接收者；复制者如果有参数槽，将它们初始化为实际参数；在这个新的活动对象的上下文中，执行这个方法的代码。
作为语法约定，参数名字可以直接写在槽名字之后（不带前缀冒号），从而隐含的声明参数槽。例如下面的方法定义：
等同于定义了：
在Self中，在字段（field）和方法之间没有区分：所有东西都是槽。访问子方法对应数据槽，变异子方法对应赋值槽。
块是Self的闭包，Self就像Smalltalk，使用“块”用于控制流程和其他职责。块文字的写法，除了方括号替代了圆括号之外，类似于其他对象文字。例如下列表达式中的块：
1 to: 5 * i By: 2 * j Do: [| :k | k print ] 一个块文字定义两个对象：一个块数据对象，和它包围的一个块方法对象。 块求值分两个阶段。第一阶段，在被求值的时候建立块对象（即块数据对象），浅层复制（clone）这个块，并给它一个指针，指向这个块在词法上外围的活动记录，然后它成为当前的活动记录。在第二阶段，通过向块发送适当的codice_26消息变体，求值这个块的方法；浅层复制块方法，并填充复制体的方法槽，使用在第一阶段确定指针初始化匿名父槽，最后执行这个块的代码。
访问槽的语法类似于Smalltalk。有三类消息可以获得：
所有消息都返回结果，所以接收者（如果有的话）和参数自身可以是其他消息的结果。下列跟随着句号的消息，意味着Self将丢弃返回的值。例如Self版本的hello world程序：
'Hello, World!' print.
组合可以通过使用圆括号来强制。在缺乏明确组合的情况下，一元消息被认为有最高优先级，其次是二元消息（组合是从左至右的），而关键字消息最低。例如计算点的加法的一个方法：
可以被无歧义的分析，其含义同于：
赋值槽在形式上如同关键字，在表达式也有关键字消息的地方，将导致一些额外的圆括号，为了避免如此，Self要求关键字消息的第一部份开始于小写字母，而后续部份开始于大写字母。例如： valid: base bottom 可以被无歧义的分析，其含义同于： valid: ((base bottom) 因为通过消息访问槽形成了Self语法的绝大部份，很多消息被发送给codice_24，codice_24可以去掉，语言因而得名。在Smalltalk-80中，相同的表达式将写为： valid := self base bottom 这里假定了codice_39、codice_40、codice_41和codice_42不是codice_24的实例变量，而事实上是方法。
当处在于提示符下键入表达式的场景时，由叫做“大厅”（lobby）的一个对象，引领用户进入Self世界。当建立一个新对象的脚本被读入系统的时候，脚本中的表达式都在大厅的上下文中求值。就是说大厅是这个脚本中所有发送给codice_24的消息的接收者。要引用在脚本中的某个现存的对象，必须通过发送一个消息到大厅才可以访问到它。
大厅的codice_45、codice_46和codice_47槽，是从大厅可以访问的对象命名空间的根。它们向用户提供三类对象： 槽codice_50允许大厅自身用名字来引用。
路径名字是一个一元选择子的序列，它描述从大厅到这个对象的路径。路径名字也是可以在大厅的上下文中求值的表达式，它产出这个对象。不是所有对象都有路径名字，只有那些从大厅可以到达的对象才有，这些对象称为周知的。
例如，原型列表的完全路径名字是codice_51。因为codice_46是父槽，它可以从路径名字表达式中省略，生成简短路径名字codice_53。大厅的codice_45不是父槽，特质对象的名字必须开始于前缀codice_45，因此列表的特质对象必须称呼为codice_56。
有两个消息与对象复制有关：
考虑一个图形用户界面有关的例子：
labelWidget copy label: 'Hello, World!'.
通过codice_49消息制作codice_59对象的一个副本，接着向它发送一个消息，将codice_60放入叫做codice_61的槽中。现在用它做点事情：
(desktop activeWindow) draw: (labelWidget copy label: 'Hello, World!').
在这个案例中，首先进行codice_62，它从codice_63对象所知道的一个窗口列表中，返回活动窗口codice_64。按从内向外从左至右的次序，接着是前面研究过的代码，它返回codice_59。最后这个组件被发送到codice_64的codice_67槽中。
在理论上，所有Self对象都是独立实体，Self既没有类也没有元类。对任何特定对象的变更，都不影响任何其他对象，但是在某些情况下，却需要它们有关联。正常的一个对象，只能理解对应于它的局部槽的消息，但拥有一个或更多的指示父（parent）对象的槽，对象可以将任何自身不理解的消息，委托（delegate）给父对象。Self采用这种方式处理，在基于类的语言中使用继承来担负的责任。委托还可以用来实现一些特征，比如名字空间和词法辖域。 这与传统的类有任何不同吗？我们考虑如下例子的含义：
myObject parent: someOtherObject.
这个句子通过改变与codice_30槽关联的值，在运行时间改变codice_69的“类”。不同于继承或词法辖域，委托对象可以在运行时间修改。
例如，假定在一个简单的账簿应用中，定义了一个对象叫做“银行帐号”（bank account）。通常建立的这个对象，具有内部的方法，比如说“存款”（deposit）和“取款”（withdraw），和任何它所需要的数据槽，比如说“余额”（balance）。这只是一个原型，它只在使用方式上特殊，因为它恰好是一个全功能的银行帐号。
为“Bob的账户”制作银行帐号对象的复制品（clone），将建立一个新对象，它起步时完全同于原型。在这种情况下，将复制（copy）包括方法和任何数据的槽。但更常用的解决方案，是首先建立一个简单对象叫做特质（trait）对象，它包含通常与一个类有关的项目。
在这个例子中，“银行账户”将没有存款和取款方法，而是将有一个父对象来做这些。采用这种方式，可以制作银行帐号对象的很多副本，但是我们仍可以通过改变在根对象中的槽，来改变全部它们的行为。
在Self中的对象可以通过包括新加的槽来修改。这可以通过被推荐使用的图形编程环境来做，或者直接使用原语codice_70。原语与正常关键字消息有相同的语法，但他它的名字开始于下划线字符。给codice_70的参数是一个对象文字，它的槽将被复制来到接收者。如下表达式：
_AddSlots: ( | newObject = ( | entries 虚拟机系统。就是说，程序不是像C语言中那样的独立实体，而是需要它们的整体内存环境来运行。这要求应用程序被装载入保存内存的大块（chunk）之中，这叫做“快照”或。这种方式的缺点，是映像有时很大并且笨重；但是调试一个映像，经常被调试一个传统程序要简单，因为运行时状态更容易检查和修改。在基于源代码和基于映像的开发之间的不同，是类似于在面向类的和面向原型的面向对象编程之间的区别。
此外，环境是为了让在系统之中的对象能快速和可持续的变更而定制的。重新构建一个“类”设计，就像从现存的祖先拖动出来方法放入新造的之中一样容易。简单任务像测试方法，可以通过制作副本来处理，拖动方法进入这个副本，接着变更它。不同于传统系统，只有变更了的对象有新代码，不需要重建任何东西来测试它。如果这个方法有效，可以简单的把它拖动回祖先之中。
Self的VM实现的性能，在某些测试之中大约是优化的C程序速度的一半。
这是通过即时编译技术达到的，它是在Self研究中首创并改进的，能够使高级语言表现得这么好。
Self的垃圾收集器使用分代垃圾回收，它按年龄分离对象。通过使用内存管理系统记录页面写，可以维护一个写屏障。这个技术给出了卓越的性能，尽管在运行一些时间之后，出现完全的垃圾收集，要花相当可观的时间。
运行系统选择性的扁平化调用结构。这给出适当的自身提速，但允许了对不同调用者类型的类型信息和多版本的代码的大量缓存。这去除了对做很多方法查找的需要，并允许条件分支语句和硬编码调用被插入，这经常能给出类似C语言的性能，而又不失去语言层面的通用性，但要建立在完全的垃圾收集系统之上。