0

I have a class with an inner class that I override. That seems to be working fine.

class Car {
   public static class CarItems
   {
      public void doStuff(){ ... }
   }
}

class Honda extends Car {
   public static class CarItems extends Car.CarItems
   {
      @Override
      public void doStuff(){ ... }
   }
}

Problem

That Car class is inside another class that I'm also overriding:

class Dealership {
   //
   // #1: Here's a list of stuff, which includes car items
   //     as defined in parent class
   //
   protected List<CarAndStuff> carsAndStuff;

   public static class CarsAndStuff {
      private List<CarItems> carItems;
      private String name;
      // ...

      //
      // #2: This only returns the items from the rest of the
      //     clutter in this class
      //
      public List<CarItems> getCarsItems() { return carsItems; }
   }

   // As defined above
   public static class CarItems { ... }
}

class HondaDealership extends Dealership {
   //
   // #3: This sub-class only cares about the items
   //
   protected List<CarItems> carItems;

   public void extractItemsFromParent() {
      List<CarItems> _items = new ArrayList<CarItems>();

      for(CarsAndStuff stuff : carsAndStuff) {
         //
         // #4: So I try to extract the items, but using my
         //     overriden method. ERROR!
         //
         carItems.addAll(carsAndStuff.getCarItems());
      }

      this.carItems = carItems;
   }

   // As defined above
   public static class CarItems extends Car.CarItems { ... }
}

Hopefully that's not too much code to follow, and it's all pretty straight forward... The error I'm getting is that on #4 Java is trying to cast from Car.CarItems up to Honda.CarItems. It says:

The method addAll(Collection<? extends Honda.CarItems>)
  in the type List<Honda.CarItems> 
  is not applicable for the arguments (List<Car.CarItems>)

If Honda.CarItems IS-A Car.CarItems, why won't it let me add a List to a List ??

rodrigo-silveira
  • 12,607
  • 11
  • 69
  • 123
  • "and it's all pretty straight forward" ... Not really. – Kakalokia May 19 '14 at 17:35
  • 1
    In your code, you are trying to add `List` to `List`. You can't do that, since a `Car.CarItems` is not necessarily a `Honda.CarItems`, and most specifically, `Car.CarItems` doesn't extend `Honda.CarItems`, but the other way around. – LJ2 May 19 '14 at 19:24

2 Answers2

1

Try having the Dealership CarItems collection use the Generics extend capability. Then, in the HondaDealership class, you can cast the list appropriately.

So, you Dealership class would look like:

public class Dealership {
    //
    // #1: Here's a list of stuff, which includes car items
    // as defined in parent class
    //
    protected List<CarsAndStuff> carsAndStuff;

    public static class CarsAndStuff {
        private List<? extends CarItems> carItems;
        private String name;

        // ...

        //
        // #2: This only returns the items from the rest of the
        // clutter in this class
        //
        public List<? extends CarItems> getCarItems() {
            return carItems;
        }
    }

    // As defined above
    public static class CarItems {
        public void doStuff() {
        }
    }
}

And your HondaDealership class would look like:

public class HondaDealership extends Dealership {
    //
    // #3: This sub-class only cares about the items
    //
    protected List<CarItems> carItems;

    public void extractItemsFromParent() {
        List<CarItems> _items = new ArrayList<CarItems>();

        for (CarsAndStuff stuff : carsAndStuff) {
            //
            // #4: So I try to extract the items, but using my
            // overriden method. ERROR!
            //
            carItems.addAll((List<CarItems>) stuff.getCarItems());
        }

        this.carItems = carItems;
    }

    // As defined above
    public static class CarItems extends Dealership.CarItems {
        @Override
        public void doStuff() {
        }
    }
}
Tony Zampogna
  • 1,928
  • 1
  • 12
  • 14
  • So that would work if I add items from Honda, but if I try to add plain Car.CarItems to an instance of Car, that doesn't work. I guess I need to rethink my design. – rodrigo-silveira May 19 '14 at 18:55
1

This may not be the best answer in the world, but will get the job done:

// Instead of addAll, add each item from CarsAndStuff.getCarItems
List<CarItems> _items = new ArrayList<CarItems>();

    for (CarsAndStuff stuff : carsAndStuff) {
        List<Car.CarItems> _carItems = stuff.getCarItems());
        for (CarItems _carItem: _carItems) {

            // ** Can't cast Car.CarItems ==> Honda.CarItems? Copy it! **
           _items.add(new CarItems(_carItem));

        }
    }

In summary, instead of casting (explicitly or implicitly) from Car.CarItems to Honda.CarItems, just make a copy of the object, thus making it a true Honda.CarItems. This requires that your Honda.CarItems implements a copy constructor, which is one extra step for you:

class Honda extends Car {
  public static class CarItems extends Car.CarItems
  {

     public CarItems(Car.CarItems items) {
         this.property_1 = items.property_1;
         this.property_2 = items.property_2;
         this.property_3 = items.property_3;

         // etc.
     }

     @Override
     public void doStuff(){ ... }
  }
}
Snake Verde
  • 604
  • 4
  • 12