'Can a trait implement an abstract method from a base class

I have a ContactableMemberHandler that is, right now, extending some RecordListHandler, but I also need a version of the contactable member handler that extend SingleRecordHandler. Of course, that version should contain the business concerns from the original...

The BaseRecordHandler look something like this:

class BaseRecordHandler<T> { 
    // a lot of implementation details irrelevant to this question...

    /**
     * 
     * @param records
     * @param onSubmit
     * @param onCheckDuplicate
     * @param onRetry
     */
    public void handle(List<T> records, Closure onSubmit, Closure onCheckDuplicate, Closure<T> onRetry) {
        boolean keepTrying = true;

        while(keepTrying) {
            try {
                onSubmit();
                keepTrying = false;
            } catch (StepFailedException ex) {
                this.handleFailure(ex, onSubmit, onCheckDuplicate, onRetry, records);
            }
        }

        for (T n : records)
            this.usedRecords.add(n);
    }

    protected abstract void handleFailure(StepFailedException ex, Closure onSubmit, Closure onCheckDuplicate, Closure<T> onRetry, List<T> newRecords) throws StepFailedException;

    // more irrelevant business logic
}

The SingleRecordHandler look like this:


@InheritConstructors
public abstract class SingleRecordHandler<T> extends BaseRecordHandler<T> {

    /**
     * @param record
     * @param onSubmit @throws StepFailedException
     * @param onCheckDuplicate
     * @param onRetry
     */
    public void handle(T record, Closure onSubmit, Closure<Boolean> onCheckDuplicate, Closure<T> onRetry) {
        this.handle([record], onSubmit, onCheckDuplicate, onRetry);
    }

    @Override
    protected void handleFailure(StepFailedException ex, Closure onSubmit, Closure onCheckDuplicate, Closure<T> onRetry,
            List<T> newRecords) throws StepFailedException {
        if (onCheckDuplicate(ex)) {
            newRecords.add(onRetry());
        }
        else {
            newRecords.pop();
            throw ex;
        }
    }
}

and the RecordListHandler look something like this:

@InheritConstructors
public abstract class RecordListHandler<T> extends BaseRecordHandler<T> {

    @Override
    protected void handleFailure(StepFailedException ex, Closure onSubmit, Closure onCheckDuplicate, Closure<T> onRetry,
            List<T> newRecords) throws StepFailedException {
        int duplicateRecordIdx = onCheckDuplicate(ex);

        if (duplicateRecordIdx > -1) {
            newRecords.push(onRetry(duplicateRecordIdx));
        } else {
            newRecords.pop();
            throw ex;
        }
    }
}

...but what if we use traits?

It sounds like converting SingleRecordHandler,RecordListHandler to traits would solve this...

...but when we go to use them like:

public class ContactableMemberListHandler extends BaseRecordHandler<ContactableMemberModel> implements RecordListHandler<ContactableMemberModel> { 
   // ... business logic
}

will handleFailure() be implemented by the traits?



Solution 1:[1]

Apparently, it does. However trait methods are only private and public, hence you'd have to make the method public.

A trait can extend a class, but you'd still have to extend that base class when you go to use the trait...

Weird...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mike Warren