2016-10-20 30 views
11

从单纯的计算机科学(或者计算linguisticis)的角度来看,我想知道的话之间的差别:Decorator,Attribute,Aspect和Trait之间有什么区别?

  • 装饰
  • 属性
  • 看点
  • 特质

各种语言以不同的方式利用这些词汇和功能。在Python,例如,装饰[根据Python的维基](重点煤矿):

装修动态改变的函数,方法,或类的功能,而不必直接使用亚类或改变源正在装饰的功能的代码。

这让我非常相似面向方面的编程工具,如PostSharp或DynamicProxy。即:

[Profile] 
    private static void SleepSync() 
    { 
     Thread.Sleep(200); 
    } 

来源:PostSharp Examples

在C#和Java(以及其它语言的无数),属性可以意味着一个装饰肥胖型图案(C#)或场(爪哇)。如图所示

而在C++通过通过内置的特质的话,我们可以用性状扩展类升压或PHP这里:https://en.wikipedia.org/wiki/Trait_(computer_programming)

所以,从“纯”的角度来看,什么是规范的定义这些实际上是什么?有没有更好的方法来定义它们?

+0

语言之间没有标准。另外,我不认为所有的语言都支持每个语言的严格定义。以Java。 Decorator = Annotation,Attribute = Field,Trait =默认方法(可能是接口)...另一方面,Aspect更像是一种软件架构概念,而不是任何一种语言的特性。 –

+1

对于这些相关的“事物”中的每一个,都有一个范式级别的术语。如果从理论的角度来看,我很难相信你无法准确地量化它们。 – Darkenor

+0

您是否真的需要在编程语言之间切换,以便讨论概念而不是语言的实际术语? Trait和Aspect的维基百科页面似乎足以让我从高层理解。 (参考:https://en.m.wikipedia.org/wiki/Aspect_(computer_programming))但是,如果你在谈论Python并且我在谈论C#,并且我们都说装饰器,那么我们的理解可能就是不同。 –

回答

3

装饰

我觉得装饰的设计模式中的条款。设计模式在许多语言中都得到认可,尤其是面向对象的。然后,作为模式的装饰器是一个包装器,它添加了正在装饰的函数或类中不存在的功能。

我能想到的最简单的例子是装饰器功能。功能

int foo(int x) 

可以通过接受第二个参数的另一个函数来装饰,做点别的吧,然后依次调用foo(),并传入原始参数x。

int bar(int x, int y) { 
    return y*y + foo(x); 
} 

虽然设计模式在类级别通常适用,这里的原理是一样的,我认为这很好地说明了什么是一个装饰意味。每种特定语言是否都遵守这一点是另一回事。一种语言可能有别的东西,称之为“装饰器” - 但对我而言,这个概念最好地与简单装饰其他功能的想法相匹配,而不改变原始代码或甚至使用继承。

另一个常见的例子是Java中的I/O类。还有就是基本

OutputStream s 

,然后你可以使用依赖于数据的类型正在处理更加专业化类装饰,或者是你希望的格式在读取数据:

OutputStream s1 = new FileOutputStream("somefile.txt"); 

OutputStream s2 = new ByteOutputStream("rawdata.hex"); 

属性

我会倾向于C#的属性理念是正确的理解,因为它不同于装饰者。一个属性分配一个语义值,该值可以因对象而异,甚至可以在使用相同属性的API之间变化。例如,我可能有两个对象:

[Logging] Object a; 
[Security] Object b; 

我可以指定一个记录属性和一个安全属性,以及这些属性的意思可能是客户端API,可检查这些属性不同。可以使用log4j来实现日志记录,并且可以使用另一个API。这里的定义更加流畅,并且可供我的代码的不同方或用户解释。当然,我们可以使用一个属性来充当装饰器,但是属性可以被使用的远不止这些。

仅用于消歧,单词属性也用于表示类的成员变量。在这里我们正在讨论将更大,更抽象的概念分配给一个已经存在的对象或类的预定义语义值。 Java调用这些注释。

从我们所说的意义上来说,我认为它是一个属性的一个限定词就是它不直接修改行为,只是间接修改行为。例如,将[Logging]属性分配给某些内容不会以任何方式更改其代码。这就像附加其他人正在寻找的名称标签。当另一个程序或应用程序看到名称标签时,它会推断某些事情并可能相应地改变其行为。但是(至少在Java中)注释或属性不会直接修改任何东西 - 再次,只是一个名称标签。在C#或支持属性的其他语言中,这可能会略有不同,在这种情况下,我会认为它们是更高级的属性或其他完全不同的属性。

看点

在面向方面的编程(AOP)的意义上的一个方面是一种自修改或自更新代码构造的。它将一段代码定义为更具延展性(减少点数),并允许特定部分在一个或多个可能的更新,补丁或代码的相同部分的不同版本之间交换。

你可以使用方面做一些与装饰器和属性相同的东西吗?当然。但为什么你会让自己头痛? AOP就像OOP的下一步,只有在必要时才能使用它。何时需要?当一个特定的应用程序出现诸如安全性或日志记录等许多“交叉问题”时 - 例如,银行应用程序。这些关切是交叉的;它们超越了传统界限,它们可以定义好类和包。当你登录时,除非你记录所有的东西,否则它不会有很好的表现。因此,这种关切是交叉的。所以当你去更新一个类的日志记录机制时,很难同时修改所有其他的类和API,但也是必要的。否则,您的日志记录现在不一致且令人困惑,并且更难以用于故障排除或监视。

为了使这些更新不那么令人头疼,引入了AspectJ等面向方面的语言。我没有碰到除此之外任何其他意思的“方面”,但可能有一些如前所述关于装饰者。一种特定的语言可能称为某个方面,但它可能更像是我们已经讨论过的其他事情之一。

特质

性状与接口的代名词,或者至少这是它似乎是在我研究的语言。

接口是一种OOP概念,它在不实现它们的情况下声明行为。创建这些预期的行为允许这些行为变得通用,并且一般不需要关注具体细节就可以调用。它由子类来实现它们。

经典的面向对象的例子是动物,有两个子类,猫和狗。

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!"); 
    } 
} 

这也是多态性的一个很好的例子 - 这些单词倾向于使非计算机人士畏缩。这只意味着猫和狗有个人行为,如果我宣布动物物体,我不在乎你给我什么样的东西。你可以给我一只猫或一只狗。因为两者都是动物,在任何情况下,我所要做的就是调用Animal对象的speak()函数,我可以放心,无论哪种情况都会发生正确的结果。每个单独的子类都知道它需要做什么。在C++中,这里的水域更加泥泞,但是一般概念是相同的(如果你想开始这个兔子洞,可以读入关键字'虚拟')。

层的总结

我希望澄清了一些混乱。看起来,正如你所说,许多不同的语言对每一种语言都有不同的含义,毫无疑问是造成了混乱。我相信如果你进一步研究它,你会发现大体上这些都是标准的含义。我已经使用多种语言(VB,C++,C#,Java,Paschal,PHP,Perl)进行了18年以上的编程,这些是我最相信作为一种标准的定义。

我当然欢迎进一步讨论我所说的话。

+2

恕我直言,特质远远超出了界面。一个接口只声明,哪些方法可以找到,但不提供实现。特质还包括定义。所以我看到一种特质更像是某种*部分班*,可以部分归为多个班级* – derM

+0

@derM正如我的回答所述,不同的语言有不同的含义。我同意特质CAN不仅仅是一个界面。我从来没有说过,他们不能仅仅是这个。当你提炼出什么特质总是与他们有时意味着什么的时候,你会发现界面是共同点。我同意那里有歧义,但这就是讨论的性质。随意发布你自己的答案,更好地解释特质。 – Tim

相关问题