title: Passing superclasses into a method where a subclass is needed
body: <p>Ok, while I tried to find a title that explains the problem I probably have to expand on it.</p>
  
  <p>Recently I implemented a small program that will be used to control a tape library. Knowing it had to work with multiple different types of tape library so the following design was developed.</p>
  
  <pre><code>interface Tapelibrary&lt;T extends TapeDrive&gt; {
      List&lt;T&gt; getListofDrives();
      void doSomethingWithDrive(T d);
  }
  
  class SpecificTapeLibrary implements Tapelibrary&lt;HPDrive&gt; {
      private List&lt;HPDrive&gt; driveList;
  
      SpecificTapeLibrary() {
          driveList.add(new HPDrive());
          driveList.add(new HPDrive());
          driveList.add(new HPDrive());
      }
  
      @Override
      public List&lt;HPDrive&gt; getListofDrives() {
        return driveList;
      }
  
      @Override
      public void doSomethingWithDrive(HPDrive d) {
         d.doSomethingHPspecific();
      }
  }
  
  abstract class TapeDrive {
      void doSomething() {
      }
  }
  
  class HPDrive extends TapeDrive {
      void doSomethingHPspecific() {
      }
  }
  </code></pre>
  
  <p>The correct tape library is determined by a factory based on command line arguments.</p>
  
  <pre><code>public static void main(String[] args) {
      Tapelibrary&lt;? extends TapeDrive&gt; t = new TapeLibraryFabric().get();
      List&lt;? extends TapeDrive&gt; listOfDrives = t.getListofDrives();
  
      // the user selects a drive by using a small UI or something
      TapeDrive selectedDrive = listOfDrives.get(0);
  
      t.doSomethingWithDrive(selectedDrive); // compiler error
  }
  </code></pre>
  
  <p>This does make sense since the compiler would have to explicitly cast the supertype TapeDrive to the subtype HPDrive which is expected by the doSomethingWithDrive(HPDrive) methods in SpecificTapeLibrary</p>
  
  <p>How would this be solved in a good oop way? I ended up not using generics and casting inside the doSomethingWithDrive method (as suggested here:<a href="https://stackoverflow.com/questions/20531533/how-to-pass-a-child-class-into-a-method-requiring-super-class-as-parameter">How to Pass a Child Class into a method requiring Super Class as parameter</a>). But that can't be the optimal solution.</p>
  
  <p>While writing this post another solution popped into my head which is much cleaner. The DriveSelector class encapsulates the selection process.</p>
  
  <pre><code>class DriveSelector {
      &lt;T&gt; T selectDrive(List&lt;T&gt; inputList) {
          // give the user an UI or something to select a drive 
          return inputList.get(0);
      }
  }
  
  // the tape library then uses the selector
  public void doSomethingWithSelectedDrive(DriveSelector selector) {
       HPDrive t = selector.selectDrive(driveList);
       t.doSomethingHPspecific();
  }
  </code></pre>
  
  <p>Any other ideas?</p>