DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Java Code Review Solution
  • Leverage Lambdas for Cleaner Code
  • Getting Started With JMS-ActiveMQ: Explained in a Simple Way
  • Binary Code Verification in Open Source World

Trending

  • How to Configure and Customize the Go SDK for Azure Cosmos DB
  • GDPR Compliance With .NET: Securing Data the Right Way
  • My LLM Journey as a Software Engineer Exploring a New Domain
  • *You* Can Shape Trend Reports: Join DZone's Software Supply Chain Security Research
  1. DZone
  2. Coding
  3. Java
  4. Traits in Java 8: Semantic, DRY-compliant, Interface-first Code

Traits in Java 8: Semantic, DRY-compliant, Interface-first Code

Learn how you can master the Trait pattern and how it can be realized in Java 8.

By 
Emil Forslund user avatar
Emil Forslund
·
Feb. 15, 16 · Analysis
Likes (11)
Comment
Save
Tweet
Share
34.6K Views

Join the DZone community and get the full member experience.

Join For Free

In this article, I will present the concept of traits and give you a concrete example of how they can be used in Java to achieve less redundancy in your object design. I will begin by presenting a fictional case where traits could be used to reduce repetition and then finish with an example implementation of the trait pattern using Java 8.

Suppose you are developing a message board software and you have identified the following as your data models: “topics”, “comments” and “attachments”. A topic has a title, a content, and an author. A comment has a content and an author. An attachment has a title and a blob. A topic can have multiple comments and attachments. A comment can also have multiple comments, but no attachments.

Soon you realize that no matter how you implement the three models, there will be code repetition in the program. If you for an example want to write a method that adds a new comment to a post, you will need to write one method for commenting topics and one for commenting comments. Writing a method that summarizes a discussion by printing out the discussion tree will have to take into consideration that a node can be either a topic, a comment or an attachment.

Since the inception of Java over 20 years ago, object-oriented programming has been the flesh and soul of the language, but during this time, other languages have experimented with other tools for organizing the structure of a program. One such tool that we use in Speedment Open Source is something called “Traits”. A trait is kind of a “micro interface” that describes some characteristic of a class design that can be found in many different components throughout the system. By referring to the traits instead of the implementing class itself you can keep the system decoupled and modular.

Let’s look at how this would change our example with the message board.

Now the different traits of each entity have been separated into different interfaces. This is good. Since Java allows us to have multiple interfaces per class, we can reference the interfaces directly when writing our business logic. In fact, the classes will not have to be exposed at all!

Traits have existed for many years in other programming languages such as Scala, PHP, Groovy, and many more. To my knowledge there is no consensus regarding what is considered a trait between different languages. On the Wikipedia page regarding traits it says that:

“Traits both provide a set of methods that implement behaviour to a class and require that the class implement a set of methods that parameterize the provided behaviour”

The following properties are named as distinctive for traits:

  • traits can be combined (symmetric sum)
  • traits can be overriden (asymmetric sum)
  • traits can be expanded (alias)
  • traits can be excluded (exclusion)

Since Java 8 you can actually fulfill most of these criteria using interfaces. You can for an example cast an implementing class of an unknown type to a union of traits using the and (&) operator, which satisfies the symmetric sum criteria. A good example of this is described here. By creating a new interface and using default implementations you can override some methods to fulfill the asymmetric sum criteria. Aliases can be created in a similar way. The only problem is exclusion. Currently java has no way of removing a method from inheritance so there is no way to prevent a child class from accessing a method defined in a trait.

If we return to the message board example, we could for an example require the implementing class to have a method getComments, but all additional logic regarding adding, removing and streaming over comments could be put in the interface.

public interface HasComments<R extends HasComments<R>> {

    // one method that parameterize the provided behaviour
    List<Comment> getComments();

    // two methods that implement the behaviour
    default R add(Comment comment) {
        getComments().add(comment);
        return (R) this;
    }

    default R remove(Comment comment) {
        getComments().remove(comment);
        return (R) this;
    }
}

If we have an object and we want to cast it to a symmetric sum of HasComments and HasContent, we could do it using the and (&) operator:

final Object obj = ...;
Optional.of(obj)
    .map(o -> (HasComments<?> & HasContent<?>) o)
    .ifPresent(sum -> {/* do something */});


If you want to read more about traits as a concept, I really suggest you read the Traits: Composable Units of Behaviour paper from 2003 by N. Schärli et al.

Trait (computer programming) Java (programming language) code style

Published at DZone with permission of Emil Forslund, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Java Code Review Solution
  • Leverage Lambdas for Cleaner Code
  • Getting Started With JMS-ActiveMQ: Explained in a Simple Way
  • Binary Code Verification in Open Source World

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!