Dar*_*nor 16 theory computer-science decorator traits aspect
从纯计算机科学(或计算语言学)的角度来看,我想知道这些词之间的区别:
各种语言以不同的方式使用这些单词和功能.在Python中,例如,Decorators [根据Python Wiki](强调我的):
装饰器动态地改变函数,方法或类的功能,而不必直接使用子类或更改正在装饰的函数的源代码.
这让我感觉非常类似于面向方面的编程工具,如PostSharp或DynamicProxy.即:
[Profile]
private static void SleepSync()
{
Thread.Sleep(200);
}
Run Code Online (Sandbox Code Playgroud)
来源:PostSharp示例
在C#和Java(以及无数其他语言)中,属性可以表示Decorator-ish模式(C#)或字段(Java).
在C++中通过boost或PhP通过内置特征词,我们可以使用特征来扩展类,如下所示:https://en.wikipedia.org/wiki/Trait_ (computer_programming)
因此,从"纯粹"的角度来看,所有这些实际上是什么的规范定义是什么?有没有更好的方法来定义它们?
Tim*_*Tim 11
装饰
我认为Decorator在设计模式方面.设计模式以多种语言识别,特别是面向对象的语言.然后,作为模式的装饰器是一个包装器,它添加了正在装饰的函数或类中不存在的功能.
我能想到的最简单的例子是装饰器功能.功能
int foo(int x)
Run Code Online (Sandbox Code Playgroud)
可以由另一个接受第二个参数的函数装饰,用它做其他事情,然后依次调用foo(),传递原始参数x.
int bar(int x, int y) {
return y*y + foo(x);
}
Run Code Online (Sandbox Code Playgroud)
虽然设计模式通常在类级别应用,但这里的原理是相同的,我认为它很好地说明了装饰器的含义.每种特定语言是否符合这一点是另一回事.一种语言可能有其他东西,它称之为"装饰者" - 但对我来说,这个概念最符合装饰一些简单的附加功能,而不改变原始代码甚至使用继承的想法.
另一个常见的例子是Java中的I/O类.有基本的
OutputStream s
Run Code Online (Sandbox Code Playgroud)
然后你可以使用更专业的类来装饰它,具体取决于所处理的数据类型,或者你希望读取数据的格式:
OutputStream s1 = new FileOutputStream("somefile.txt");
Run Code Online (Sandbox Code Playgroud)
要么
OutputStream s2 = new ByteOutputStream("rawdata.hex");
Run Code Online (Sandbox Code Playgroud)
属性
我倾向于将C#的属性理解为正确的理解,因为它与装饰者不同.属性分配的语义值可以因用户而异,甚至可以在使用相同属性的API之间.例如,我可能有两个功能:
[Logging] private void a() { ... }
[Security] private void b() { ... }
Run Code Online (Sandbox Code Playgroud)
我可以为其分配一个日志属性和一个安全属性,这些属性的含义可能与检查这些属性的客户端API不同.可以使用log4j来实现日志记录,可以使用另一个API.这里的定义更加流畅,并且可以由我的代码的不同方或用户进行解释.当然可以使用属性作为装饰器,但属性可以用于更多.
仅仅为了消除歧义,word属性也用于表示类的成员变量.在这里,我们讨论的是更大,更抽象的概念,即为现有对象或类分配预定义的语义值.Java称这些注释为.
在我看来,作为一个属性的一个限定词,就我们所说的而言,它不会间接地直接修改行为.例如,将[Logging]属性分配给某些内容不会以任何方式更改其代码.这就像附上其他人正在寻找的名牌.当另一个程序或应用程序看到名称标签时,它会推断出某些事情,并可能相应地改变其行为.但是(至少在Java中)注释或属性不直接修改任何东西 - 再次,只是一个名称标签.在C#或支持属性的其他语言中,这可能略有不同,在这种情况下,我会将它们视为更高级的属性或完全不同的其他属性.
方面
面向方面编程(AOP)意义上的一个方面是一种自修改或自更新的代码构造.它将一段代码定义为更具延展性(一个切入点),并允许特定部分在一个或多个可能的更新,补丁或同一代码段的不同版本之间进行交换.
你可以使用方面做一些与装饰器和属性相同的东西吗?当然.但是你为什么要给自己头痛呢?AOP就像是OOP的下一步,只有在必要时才应该使用它.什么时候需要?当特定应用程序存在许多"交叉问题"时,例如安全性或日志记录 - 例如,银行应用程序.这些问题交叉; 它们跨越传统的界限,形成了很好的定义的类和包.当你记录时,除非你记录所有内容,否则它不会带来很多好处; 因此,这种关注是贯穿各领域的.因此,当您更新一个类的日志记录机制时,很难同时修改所有其他类和API,但它也是必要的.否则,您的日志记录现在不一致且令人困惑,并且更难以用于故障排除或监视.
为了使这些类型的更新不那么令人头疼,引入了面向方面的语言,如AspectJ.我没有遇到过与此不同的"方面",但可能有一些如前所述的装饰器.一种特定的语言可能会将某些东西称为一个方面,但它可能看起来更像是我们已经讨论过的其他事情.
特征
特质是界面的同义词,或者至少是它在我研究过的语言中的表现.
接口是一种OOP概念,它在不实现行为的情况下声明行为.创建这些预期的行为可以使这些行为变得通用,并且可以在不关心细节的情况下进行一般性调用.留给子类来实现它们.
经典的OOP示例是Animal,有两个子类,Cat和Dog.
public interface/trait Animal {
public void speak();
}
public class Cat implements Animal {
public void speak() {
output("Meow.");
}
}
public class Dog implements Animal {
public void speak() {
output("Bark!");
}
}
Run Code Online (Sandbox Code Playgroud)
这也是多态性的一个很好的例子 - 其中一个倾向于使非计算机人员畏缩的词.它只是意味着猫和狗有个人行为,如果我宣布一个动物对象,我不在乎你给我什么样的.你可以给我一只猫或一只狗.因为两者都是动物,在任何一种情况下,我所要做的就是调用我的Animal对象的speak()函数,我可以放心,在任何一种情况下都会出现正确的结果.每个子类都知道它需要做什么.在C++中,这里的水域更加泥泞,但一般概念是相同的(如果你想从兔子洞开始,请阅读关键词'虚拟').
包起来
我希望能够解决一些困惑.正如你所说,似乎许多不同的语言对于这些语言都有许多不同的含义,这无疑会导致混乱.我相信如果你进一步研究它,你会发现这些是标准的含义.我已经用多种语言(VB,C++,C#,Java,Paschal,PHP,Perl)编程了18年以上,这些是我认为最适合作为一种标准的定义.
我当然欢迎进一步讨论我所说的话.