1

I try to write a simple example of the decorator pattern.

I have a Printable interface, a concrete classes for printing and abstract class for decorator:

// for all objects that can be printed
interface Printable {
  public void print();
}


// classes for decorating
class DisplayPrinter implements Printable {
  public void print() {
    System.out.println("Print to the display");
  }
}

class PaperPrinter implements Printable {
  public void print() {
    System.out.println("Print to the paper");
  }
}


// printer decorator for all possible decorators
abstract class PrinterDecorator implements Printable {
  private Printable printer;

  public PrinterDecorator(Printable p) {
    printer = p;
  }

  public void print() {
    if (printer != null)
      printer.print();
  }
}

Note that I use a constructor in abstract PrinterDecorator. So, then I wrote two concrete decorators for printing header and footer of the base content to be printed. Here the footer decorator is:

class FooterPrinterDecorator extends PrinterDecorator {
  /*public FooterPrinterDecorator(Printable p) {
    super(p);
  }*/

  public void print() {
    super.print();
    System.out.println("Footer");
  }
}

Here I want the PrinterDecorator children not to redeclare the parent constructor. But I get the next error if I run with comments above:

error: constructor FooterPrinterDecorator in class FooterPrinterDecorator cannot be applied to given types;
Printable one = new FooterPrinterDecorator(new DisplayPrinter());
                ^
required: no arguments
found: DisplayPrinter
reason: actual and formal argument lists differ in length

Also I tried to write default constructor in parent decorator manually. In that case the compiler gives me the same error, but in other context (it expect constructor without arguments even if I give the Printable as a parameter. The call to the constructor:

Printable one = new FooterPrinterDecorator(new DisplayPrinter());

So, can I omit the duplication of the parent constructor in its children?

Bogdan
  • 558
  • 2
  • 8
  • 22
  • @brso05, yes, I tried. But It does not solve the issue. I've updated the error message and the call to the constructor. – Bogdan Apr 20 '17 at 19:55

2 Answers2

2

You can't; if your parent class has no default constructor, each child has to implement a constructor that calls the parent's. That is to maintain encapsulation, and because constructors are not inherited like method.

What you could do, though, is to have a method instead of a constructor in the PrinterDecorator:

abstract class PrinterDecorator implements Printable {
  private Printable printer;

  public void setDecorator(Printable p) {
    printer = p;
  }

  public void print() {
    if (printer != null)
      printer.print();
  }
}

Now your children don't need to mess with that method, they will inherit as is.

Luan Nico
  • 5,376
  • 2
  • 30
  • 60
  • This is a correct answer and this technique saves the work of writing the boilerplate constructors. Though, it introduces a temporal coupling: 'setDecorator' must be called exactly once at the right time. If somebody forgets to call it, it will lead to error. If somebody calls it more times, even consciously, that will also lead to ugly situations. So my suggestion is: consider using those boilerplate constructors (even your IDE generates it) and make printer field 'final'. – pcjuzer Apr 21 '17 at 07:42
1

Answer is no. Constructors are not inherited in java. You see this error because class FooterPrinterDecorator has only default constructor that takes no arguments (required: no arguments).

See Java Constructor Inheritance

Community
  • 1
  • 1
reynev
  • 326
  • 2
  • 5