Trait (computer programming)

Last updated

In computer programming, a trait is a concept used in programming languages which represents a set of methods that can be used to extend the functionality of a class. [1] [2]

Contents

Rationale

In object-oriented programming, behavior is sometimes shared between classes which are not related to each other. For example, many unrelated classes may have methods to serialize objects to JSON. Historically, there have been several approaches to solve this without duplicating the code in every class needing the behavior. Other approaches include multiple inheritance and mixins, but these have drawbacks: the behavior of the code may unexpectedly change if the order in which the mixins are applied is altered, or if new methods are added to the parent classes or mixins.

Traits solve these problems by allowing classes to use the trait and get the desired behavior. If a class uses more than one trait, the order in which the traits are used does not matter. The methods provided by the traits have direct access to the data of the class.

Characteristics

Traits combine aspects of protocols (interfaces) and mixins. Like an interface, a trait defines one or more method signatures, of which implementing classes must provide implementations. Like a mixin, a trait provides additional behavior for the implementing class.

In case of a naming collision between methods provided by different traits, the programmer must explicitly disambiguate which one of those methods will be used in the class; thus manually solving the diamond problem of multiple inheritance. This is different from other composition methods in object-oriented programming, where conflicting names are automatically resolved by scoping rules.

Operations which can be performed with traits include: [3] [4]

If a method is excluded from a trait, that method must be provided by the class that consumes the trait, or by a parent class of that class. This is because the methods provided by the trait might call the excluded method.

Trait composition is commutative (i.e. given traits A and B, A + B is equivalent to B + A) and associative (i.e. given traits A, B, and C, (A + B) + C is equivalent to A + (B + C)). [1]

Limitations

While traits offer significant advantages over many alternatives, they do have their own limitations.

Required methods

If a trait requires the consuming class to provide certain methods, the trait cannot know if those methods are semantically equivalent to the trait's needs. For some dynamic languages, such as Perl, the required method can only be identified by a method name, not a full method signature, making it harder to guarantee that the required method is appropriate.

Excluding methods

If a method is excluded from a trait, that method becomes a 'required' method for the trait because the trait's other methods might call it.

Supported languages

Traits come originally from the programming language Self [5] and are supported by the following programming languages:

Examples

C#

On C# 8.0, it is possible to define an implementation as a member of an interface.

usingSystem;namespaceCSharp8NewFeatures;interfaceILogger{// Traditional interface methodsvoidLog(stringmessage);voidLogError(Exceptionexception);// Default interface methodvoidLogWarning(stringmessage){Console.WriteLine(message);}}classLogger:ILogger{publicvoidLog(stringmessage){Console.WriteLine(message);}publicvoidLogError(Exceptionexception){Console.WriteLine(exception.ToString());}}classProgram{staticvoidMain(string[]args){ILoggerlogger=newLogger();logger.LogWarning("Some warning message");}}

PHP

This example uses a trait to enhance other classes:

// The templatetraitTSingleton{privatestatic$_instance=null;privatefunction__construct(){}// Must have private default constructor and be aware not to open it in the classpublicstaticfunctiongetInstance(){if(null===self::$_instance){self::$_instance=newself();}returnself::$_instance;}}classFrontController{useTSingleton;}// Can also be used in already extended classesclassWebSiteextendsSomeClass{useTSingleton;}

This allows simulating aspects of multiple inheritance:

traitTBounding{public$x,$y,$width,$height;}traitTMoveable{publicfunctionmoveTo($x,$y){// …}}traitTResizeable{publicfunctionresize($newWidth,$newHeight){// …}}classRectangle{useTBounding,TMoveable,TResizeable;publicfunctionfillColor($color){// …}}

Rust

A trait in Rust declares a set of methods that a type must implement. [46] Rust compilers require traits to be explicated, which ensures the safety of generics in Rust.

// type T must have the "Ord" trait// so that ">" and "<" operations can be donefnmax<T: Ord>(a: &[T])-> Option<&T>{letmutresult=a.first()?;fornina{if*n>*result{result=&n;}}Some(result)}

To simplify tedious and repeated implementation of traits like Debug and Ord, the derive macro can be used to request compilers to generate certain implementations automatically. [47] Derivable traits include: Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord and Hash.

See also

Related Research Articles

In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state and implementations of behavior. In many languages, the class name is used as the name for the class, the name for the default constructor of the class, and as the type of objects generated by instantiating the class; these distinct concepts are easily conflated. Although, to the point of conflation, one could argue that is a feature inherent in a language because of its polymorphic nature and why these languages are so powerful, dynamic and adaptable for use compared to languages without polymorphism present. Thus they can model dynamic systems more easily.

Multiple inheritance is a feature of some object-oriented computer programming languages in which an object or class can inherit features from more than one parent object or parent class. It is distinct from single inheritance, where an object or class may only inherit from one particular object or class.

<span class="mw-page-title-main">Ruby (programming language)</span> General-purpose programming language

Ruby is an interpreted, high-level, general-purpose programming language which supports multiple programming paradigms. It was designed with an emphasis on programming productivity and simplicity. In Ruby, everything is an object, including primitive data types. It was developed in the mid-1990s by Yukihiro "Matz" Matsumoto in Japan.

In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes a group of objects that are treated the same way as a single instance of the same type of object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.

Programming languages can be grouped by the number and types of paradigms supported.

In computer science, a dynamic programming language is a class of high-level programming languages, which at runtime execute many common programming behaviours that static programming languages perform during compilation. These behaviors could include an extension of the program, by adding new code, by extending objects and definitions, or by modifying the type system. Although similar behaviors can be emulated in nearly any language, with varying degrees of difficulty, complexity and performance costs, dynamic languages provide direct tools to make use of them. Many of these features were first implemented as native features in the Lisp programming language.

In object-oriented programming languages, a mixin is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin's methods depends on the language. Mixins are sometimes described as being "included" rather than "inherited".

The fragile base class problem is a fundamental architectural problem of object-oriented programming systems where base classes (superclasses) are considered "fragile" because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class.

In object-oriented programming, in languages such as C++, and Object Pascal, a virtual function or virtual method is an inheritable and overridable function or method for which dynamic dispatch is facilitated. This concept is an important part of the (runtime) polymorphism portion of object-oriented programming (OOP). In short, a virtual function defines a target function to be executed, but the target might not be known at compile time.

In computer programming, named parameters, named-parameter arguments, named arguments or keyword arguments refer to a computer language's support for function calls to clearly associate each argument with a given parameter parameter within the function call.

In object-oriented programming, inheritance is the mechanism of basing an object or class upon another object or class, retaining similar implementation. Also defined as deriving new classes from existing ones such as super class or base class and then forming them into a hierarchy of classes. In most class-based object-oriented languages like C++, an object created through inheritance, a "child object", acquires all the properties and behaviors of the "parent object", with the exception of: constructors, destructors, overloaded operators and friend functions of the base class. Inheritance allows programmers to create classes that are built upon existing classes, to specify a new implementation while maintaining the same behaviors, to reuse code and to independently extend original software via public classes and interfaces. The relationships of objects or classes through inheritance give rise to a directed acyclic graph.

In programming languages, an abstract type is a type in a nominative type system that cannot be instantiated directly; a type that is not abstract – which can be instantiated – is called a concrete type. Every instance of an abstract type is an instance of some concrete subtype. Abstract types are also known as existential types.

An interface in the Java programming language is an abstract type that is used to declare a behavior that classes must implement. They are similar to protocols. Interfaces are declared using the interface keyword, and may only contain method signature and constant declarations. All methods of an Interface do not contain implementation as of all versions below Java 8. Starting with Java 8, default and static methods may have implementation in the interface definition. Then, in Java 9, private and private static methods were added. At present, a Java interface can have up to six different types.

In computer programming, an enumerated type is a data type consisting of a set of named values called elements, members, enumeral, or enumerators of the type. The enumerator names are usually identifiers that behave as constants in the language. An enumerated type can be seen as a degenerate tagged union of unit type. A variable that has been declared as having an enumerated type can be assigned any of the enumerators as a value. In other words, an enumerated type has values that are different from each other, and that can be compared and assigned, but are not specified by the programmer as having any particular concrete representation in the computer's memory; compilers and interpreters can represent them arbitrarily.

In computer programming, an anonymous function is a function definition that is not bound to an identifier. Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function. Anonymous functions are ubiquitous in functional programming languages and other languages with first-class functions, where they fulfil the same role for the function type as literals do for other data types.

Moose is an extension of the object system of the Perl programming language. Its stated purpose is to bring modern object-oriented language features to Perl 5, and to make object-oriented Perl programming more consistent and less tedious.

<span class="mw-page-title-main">Composition over inheritance</span> Software design pattern

Composition over inheritance in object-oriented programming (OOP) is the principle that classes should favor polymorphic behavior and code reuse by their composition over inheritance from a base or parent class. Ideally all reuse can be achieved by assembling existing components, but in practice inheritance is often needed to make new ones. Therefore inheritance and object composition typically work hand-in-hand, as discussed in the book Design Patterns (1994).

Object-Oriented Programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data and code. The data is in the form of fields, and the code is in the form of procedures.

Kotlin is a cross-platform, statically typed, general-purpose high-level programming language with type inference. Kotlin is designed to interoperate fully with Java, and the JVM version of Kotlin's standard library depends on the Java Class Library, but type inference allows its syntax to be more concise. Kotlin mainly targets the JVM, but also compiles to JavaScript or native code via LLVM. Language development costs are borne by JetBrains, while the Kotlin Foundation protects the Kotlin trademark.

<span class="mw-page-title-main">Strongly typed identifier</span>

A strongly typed identifier is user-defined data type which serves as an identifier or key that is strongly typed. This is a solution to the "primitive obsession" code smell as mentioned by Martin Fowler. The data type should preferably be immutable if possible. It is common for implementations to handle equality testing, serialization and model binding.

References

  1. 1 2 3 Schärli, Nathanael; Ducasse, Stéphane; Nierstrasz, Oscar; Black, Andrew P. (2003). "Traits: Composable Units of Behaviour" (PDF). Proceedings of the European Conference on Object-Oriented Programming (ECOOP). Lecture Notes in Computer Science. Springer. 2743: 248–274. CiteSeerX   10.1.1.1011.8 . doi:10.1007/978-3-540-45070-2_12. ISBN   978-3-540-45070-2.
  2. Ducasse, Stéphane; Nierstrasz, Oscar; Schärli, Nathanael; Wuyts, Roel; Black, Andrew P. (March 2006). "Traits: A mechanism for fine-grained reuse". ACM Transactions on Programming Languages and Systems. 28 (2): 331–388. CiteSeerX   10.1.1.64.2480 . doi:10.1145/1119479.1119483. S2CID   16434119.
  3. Fisher, Kathleen; Reppy, John (2003). "Statically typed traits" (PDF). University of Chicago. Archived (PDF) from the original on May 17, 2004.{{cite journal}}: Cite journal requires |journal= (help)
  4. Fisher, Kathleen; Reppy, John (2004). A typed calculus of traits (PDF). 11th Workshop on Foundations of Object-oriented Programming. University of Chicago.
  5. Curry, Gael; Baer, Larry; Lipkie, Daniel; Lee, Bruce (1982). Traits: An approach to multiple-inheritance subclassing. SIGOA Conference on Office Information Systems. Philadelphia, Pennsylvania, USA: ACM Press. pp. 1–9. doi:10.1145/966873.806468.
  6. Van Cutsem, Tom; Bergel, Alexandre; Ducasse, Stéphane; De Meuter, Wolfgang (2009). Adding State and Visibility Control to Traits Using Lexical Nesting (PDF). European Conference on Object-Oriented Programming (ECOOP 2009). Lecture Notes in Computer Science. Vol. 5653. Springer-Verlag. pp. 220–243. CiteSeerX   10.1.1.372.1265 . doi:10.1007/978-3-642-03013-0_11. ISBN   978-3-642-03012-3.
  7. "Default interface methods". What's new in C# 8.0. Microsoft. Retrieved November 29, 2019.
  8. "Interfaces in C# 8.0 gets a makeover". Default Implementation in Interfaces in C# 8.0. Talking Dotnet. 9 September 2019. Retrieved November 29, 2019.
  9. "iterator_traits<Iterator>". Standard Template Library. SGI.
  10. Myers, Nathan C. (June 1995). "Traits: a new and useful template technique". C++ Report. Retrieved January 23, 2016.
  11. Abrahams, David. "Generic Programming Techniques: Traits". Boost C++ Libraries. Retrieved January 23, 2016.
  12. "Traits". The D Language Reference. Digital Mars. Retrieved January 23, 2016.
  13. "std.traits". The D Language — Library Reference. Digital Mars. Retrieved January 23, 2016.
  14. "Classes". The D Language Reference. Digital Mars. Retrieved January 23, 2016.
  15. Steele, Guy; Maessen, Jan-Willem (June 11, 2006). "Fortress Programming Language Tutorial" (PDF). Sun Microsystems. Retrieved January 23, 2016.
  16. "Object Orientation: Traits". The Groovy Programming Language. Retrieved January 23, 2016.
  17. "Haxe 2.4.0 - Haxe - The Cross-platform Toolkit". Haxe - The Cross-platform Toolkit. Retrieved 2017-09-12.
  18. "Manual - Haxe - The Cross-platform Toolkit". Haxe - The Cross-platform Toolkit. Retrieved 2017-09-12.
  19. "Default Methods". The Java Tutorials. Oracle. Retrieved January 23, 2016.
  20. Liquori, Luigi; Spiwack, Arnaud (2008). "FeatherTrait: A Modest Extension of Featherweight Java". ACM Transactions on Programming Languages and Systems. 30 (2): 11:1. doi: 10.1145/1330017.1330022 . S2CID   17231803.
  21. Liquori, Luigi; Spiwack, Arnaud (2008). "Extending FeatherTrait Java with Interfaces". Theoretical Computer Science. 398 (1–3): 243–260. doi: 10.1016/j.tcs.2008.01.051 . S2CID   12923128.
  22. Bono, Viviana; Mensa, Enrico; Naddeo, Marco (September 2014). Trait-oriented Programming in Java 8. International Conference on Principles and Practices of Programming on the Java Platform: virtual machines, languages, and tools (PPPJ ’14). pp. 181–6. CiteSeerX   10.1.1.902.161 . doi:10.1145/2647508.2647520.
  23. Forslund, Emil (February 3, 2016). "Definition of the Trait Pattern in Java". Age of Java. Archived from the original on August 4, 2016. Retrieved February 3, 2016.
  24. Seliger, Peter (April 11, 2014). "The Many Talents of JavaScript" . Retrieved January 23, 2015.
  25. "Traits.js: Traits for JavaScript" . Retrieved January 23, 2016.
  26. Van Cutsem, Tom; Miller, Mark S. (2012). "Robust Trait Composition for Javascript" (PDF). Science of Computer Programming. Retrieved January 23, 2016.
  27. "CocktailJS" . Retrieved January 23, 2016.
  28. mauro3. "SimpleTraits.jl". GitHub . Retrieved March 23, 2017.
  29. "Interfaces". Kotlin Reference. JetBrains. Retrieved January 23, 2016.
  30. Breslav, Andrey (May 29, 2015). "Kotlin M12 is out!". Kotlin Blog. JetBrains. Retrieved January 23, 2016.
  31. "Traits". Lasso Language Guide. LassoSoft. January 6, 2014. Retrieved January 23, 2016.
  32. chromatic (April 30, 2009). "The Why of Perl Roles" . Retrieved January 23, 2016.
  33. Curtis "Ovid" Poe. "Corinna OOP Proposal". Corinna RFC. Retrieved September 30, 2022.
  34. "Traits". PHP Documentation. The PHP Group. Retrieved January 23, 2016.
  35. Marr, Stefan (January 9, 2011). "Request for Comments: Horizontal Reuse for PHP". PHP.net wiki. The PHP Group. Retrieved January 31, 2011.
  36. Perä, Teppo. "py3traits Documentation" . Retrieved January 23, 2016.
  37. Perä, Teppo (2015-03-25). "py2traits". GitHub . Retrieved January 23, 2016.
  38. "Higher Order Mixin Classes". Archived from the original on 2016-10-09.
  39. "Traits". The Racket Reference. Retrieved January 23, 2016.
  40. David Naseby (February 14, 2004). "Traits in Ruby". Ruby Naseby. Retrieved January 23, 2016.
  41. "Traits". The Rust Programming Language. Retrieved September 30, 2019.
  42. "Traits". A Tour of Scala. École polytechnique fédérale de Lausanne . Retrieved January 23, 2016.
  43. Neward, Ted (April 29, 2008). "The busy Java developer's guide to Scala: Of traits and behaviors". IBM developerWorks. IBM. Retrieved January 23, 2016.
  44. "Traits in 10 minutes". Pharo: The CollaborActive Book. Retrieved January 23, 2016.
  45. Hollemans, Matthijs (July 22, 2015). "Mixins and Traits in Swift 2.0" . Retrieved January 23, 2016.
  46. "Traits - Introduction to Programming Using Rust".
  47. "Traits - the Rust Programming Language".