Trait (computer programming)

Last updated

In computer programming, a trait is a language concept that 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. [44] 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. [45] Derivable traits include: Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord and Hash.

See also

Related Research Articles

In object-oriented programming, a class defines the shared aspects of objects created from the class. The capabilities of a class differ between programming languages, but generally the shared aspects consist of state (variables) and behavior (methods) that are each either associated with a particular object or with all objects of that class.

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.

In object-oriented programming, an interface or protocol type is a data type that acts as an abstraction of a class. It describes a set of method signatures, the implementations of which may be provided by multiple classes that are otherwise not necessarily related to each other. A class which provides the methods listed in a protocol is said to adopt the protocol, or to implement the interface.

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

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 such as is often used in C++ and Object Pascal, a virtual function or virtual method is an inheritable and overridable function or method that is dispatched dynamically. Virtual functions are an important part of (runtime) polymorphism in object-oriented programming (OOP). They allow for the execution of target functions that were not precisely identified 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 within the function call.

In computer programming, a callback is a function that is stored as data and designed to be called by another function – often back to the original abstraction layer.

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.

Programming languages are used for controlling the behavior of a machine. Like natural languages, programming languages follow rules for syntax and semantics.

In mathematical logic and computer science, some type theories and type systems include a top type that is commonly denoted with top or the symbol ⊤. The top type is sometimes called also universal type, or universal supertype as all other types in the type system of interest are subtypes of it, and in most cases, it contains every possible object of the type system. It is in contrast with the bottom type, or the universal subtype, which every other type is supertype of and it is often that the type contains no members at all.

In programming languages, an abstract type is a type in a nominative type system that cannot be instantiated directly; by contrast, a concrete typecan be instantiated directly. Instantiation of an abstract type can occur only indirectly, via a concrete subtype.

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.

Moose is an extension of the object system of the Perl programming language. Its stated purpose is to bring modern object-oriented programming 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).

<span class="mw-page-title-main">Object-oriented programming</span> Programming paradigm based on the concept of objects

Object-oriented programming (OOP) is a programming paradigm based on the concept of objects, which can contain data and code: data in the form of fields, and code in the form of procedures. In OOP, computer programs are designed by making them out of objects that interact with one another.

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. 2743. Springer: 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. Steele, Guy; Maessen, Jan-Willem (June 11, 2006). "Fortress Programming Language Tutorial" (PDF). Sun Microsystems. Retrieved January 23, 2016.
  13. "Object Orientation: Traits". The Groovy Programming Language. Retrieved January 23, 2016.
  14. "Haxe 2.4.0 - Haxe - The Cross-platform Toolkit". Haxe - The Cross-platform Toolkit. Retrieved 2017-09-12.
  15. "Manual - Haxe - The Cross-platform Toolkit". Haxe - The Cross-platform Toolkit. Retrieved 2017-09-12.
  16. "Default Methods". The Java Tutorials. Oracle. Retrieved January 23, 2016.
  17. 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.
  18. 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.
  19. 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.
  20. 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.
  21. Seliger, Peter (April 11, 2014). "The Many Talents of JavaScript" . Retrieved January 23, 2015.
  22. "Traits.js: Traits for JavaScript" . Retrieved January 23, 2016.
  23. Van Cutsem, Tom; Miller, Mark S. (2012). "Robust Trait Composition for Javascript" (PDF). Science of Computer Programming. Retrieved January 23, 2016.
  24. "CocktailJS" . Retrieved January 23, 2016.
  25. mauro3. "SimpleTraits.jl". GitHub . Retrieved March 23, 2017.{{cite web}}: CS1 maint: numeric names: authors list (link)
  26. "Interfaces". Kotlin Reference. JetBrains. Retrieved January 23, 2016.
  27. Breslav, Andrey (May 29, 2015). "Kotlin M12 is out!". Kotlin Blog. JetBrains. Retrieved January 23, 2016.
  28. "Traits". Lasso Language Guide. LassoSoft. January 6, 2014. Retrieved January 23, 2016.
  29. "Modular Docs - Mojo🔥 changelog". docs.modular.com. Retrieved 2023-12-13.
  30. chromatic (April 30, 2009). "The Why of Perl Roles" . Retrieved January 23, 2016.
  31. Curtis "Ovid" Poe. "Corinna OOP Proposal". Corinna RFC. Retrieved September 30, 2022.
  32. "Traits". PHP Documentation. The PHP Group. Retrieved January 23, 2016.
  33. Marr, Stefan (January 9, 2011). "Request for Comments: Horizontal Reuse for PHP". PHP.net wiki. The PHP Group. Retrieved January 31, 2011.
  34. Perä, Teppo. "py3traits Documentation" . Retrieved January 23, 2016.
  35. Perä, Teppo (2015-03-25). "py2traits". GitHub . Retrieved January 23, 2016.
  36. "Higher Order Mixin Classes". Archived from the original on 2016-10-09.
  37. "Traits". The Racket Reference. Retrieved January 23, 2016.
  38. David Naseby (February 14, 2004). "Traits in Ruby". Ruby Naseby. Retrieved January 23, 2016.
  39. "Traits". The Rust Programming Language. Retrieved September 30, 2019.
  40. "Traits". A Tour of Scala. École polytechnique fédérale de Lausanne . Retrieved January 23, 2016.
  41. Neward, Ted (April 29, 2008). "The busy Java developer's guide to Scala: Of traits and behaviors". IBM developerWorks. IBM. Retrieved January 23, 2016.
  42. "Traits in 10 minutes". Pharo: The CollaborActive Book. Retrieved January 23, 2016.
  43. Hollemans, Matthijs (July 22, 2015). "Mixins and Traits in Swift 2.0" . Retrieved January 23, 2016.
  44. "Traits - Introduction to Programming Using Rust".
  45. "Traits - the Rust Programming Language".