Tuesday, April 5, 2011

Stopping inheritance without using final

Is there any other method of stopping inheritance of a class apart from declaring it as final or by declaring its constructor as private?

From stackoverflow
  • A comment

    //Do not inherit please
    
    Chris Lively : +1 for creativity.
    Otávio Décio : +1 for being nice.
    vava : I actually believe that's the best solution ever. You could even describe why it shouldn't to be inherited from.
    eleven81 : Too bad that they might never see the source code.
    Nick Fortescue : Yes, clearly it should be a javadoc comment :-)
  • Final was created to solve this problem.

  • I'd have to say it's typically bad form. Though there are almost always cases where something is valid, I'd have to saying stopping inheritance in an OO world is normally not a good idea. Read up on the Open-Closed Principle and here. Protect your functionality but don't make it impossible for the guy who comes in and supports it...

    Peter Štibraný : Inheritance is way overrated. Unless you design your class for subclassing, you better avoid it.
    jcollum : +1, I'm betting that Uncle Bob Martin knows more about OO than just about anyone here.
    Jon Skeet : +1 to Peter's comment. As I've said elsewhere (many times!) I wish classes were sealed (C#) / final (Java) by default. Inheritance is great, when you really need it - but it can be a pain if you just use it without thinking carefully about it.
    Michael Myers : "Design and document for inheritance or else prohibit it." -- Josh Bloch, Effective Java Item 17
    Mark G : Read Michael Feather's book "Working Effectively with Legacy Code". It's gotten me through a number of brownfield projects and things like classes and methods you can't touch are major pain points. Even if you didn't intend for it, feature XYZ will need it. All about future proofing...
    Jon Skeet : @Mark G: Inheritance restricts changes in implementation, so I don't regard allowing it as future-proofing at all. It *limits* future changes rather than allowing them.
    Mark G : @Jon Skeet: I guess in my experience I've just not seen it. Take any of the dialogs in the .NET BCL (Open/Save/Print), can't do a danged thing with them because they're sealed, major pain. But this discussion should probably be in a different question with the tag of 'Subjective'
  • Two more options:

    • make each method final, so people can't override them. You avoid accidental calling of methods from subclass this way. This doesn't stop subclassing though.

    • put check into constructor for class:

      if (this.getClass() != MyClass.class) {
          throw new RuntimeException("Subclasses not allowed");
      }
      

      Then nobody will be able to instantiate subclass of your class.

    (Not that I suggest using these techniques, it just came to my mind. I would use final class and/or private constructor)

    Michael Myers : Rats, I was just going to post the exception one myself.
    Tom Hawtin - tackline : Except if the finalize method is overriden, the instance can be recovered.
    Michael Myers : @Tom: two wrongs make an evil!
    Outlaw Programmer : +1 I didn't think there would be a real answer to this question, but I guess this is as close as you're going to get.
    Joshua : @Tom: this might break the no two security managers rule
    Chris Lively : This doesn't prevent you from overriding the constructor...
    Peter Štibraný : @Chris Lively: Constructor from super class must always be called. You can 'override' constructor (there is no such thing as overriding constructor though, as constructor is not inherited), but you cannot 'skip' constructor from super class.
  • Using final is the canonical way.

    public final class FinalClass {
      // Class definition
    }
    

    If you want to prevent individual methods from being overridden, you can declare them as final instead. (I'm just guessing here, as to why you would want to avoid making the whole class final.)

    duffymo : Reasons similar to java.lang.String, I'd guess.
    Bill the Lizard : String is final.
    • Use final
    • Use private constructors
    • Use a comment:

      // do not inherit

    • Use a javadoc comment

    • Make every method final, so people can't override them
    • Use a runtime check in the class constructor:

      if (this.getClass() != MyClass.class) { throw new RuntimeException("Subclasses not allowed"); }

    eleven81 : The comment idea really does not make much sense. A JavaDoc comment makes a lot more sense, but is still not foolproof.
  • Make your constructors private and provide factory functions to create instances.

    This can be especially helpful when you want to choose an appropriate implementation from multiple, but don't want to allow arbitrary subclassing as in

    abstract class Matrix {
       public static Matrix fromDoubleArray(double[][] elemens) {
         if (isSparse(elements)) {
          return new SparseMatrix(elements);
        } else {
          return new DenseMatrix(elements);
        }
      }
      private Matrix() { ... }  // Even though it's private, inner sub-classes can still use it
      private static class SparseMatrix extends Matrix { ... }
    }
    

0 comments:

Post a Comment