Cast to an abstract class...how this is possible?

21,982

Solution 1

This is the distinction between runtime type (actual type) and compile-time type.

The typecast to an abstract class MachineComponent is fine, because the actual object instance will actually be some non-abstract subclass of MachineComponent that implements all of the abstract methods.

The abstract MachineComponent class is the compile-time type of the assigned variable. But no actual instance is (or can be) created with that abstract class.

Solution 2

The isTree is only abstract for the abstract class. Once the class has been initialized as a non-abstract, casting it to an abstract will not change its memory. Therefore, calling the method on an abstract class effectively calls it on the concrete implementation.

The reason why it's useful is for passing subclasses around via the abstract implementation.

Let's say a String class has 'length' method. There's no need to have a function for every possible String-type subclass. Instead, you cast to the basic (abstract) String that has the 'length' implementation, and pass that around.

Solution 3

OK - let's try again:

Q: Can you cast to an abstract class?

A: Sure - of course you can

For example:

public class UseAbstract
{
  public static void main (String[] args)
  {
    // Instantiate an abstract class
    AbstractPet myDog = new Dog ();
    myDog.sound ();

    // Instantiate a concrete class
    Cat myCat = new Cat ();
    myCat.sound ();

    // Cast a concrete class to an abstract class
    AbstractPet somePet = (AbstractPet)myCat;
    somePet.sound ();
  }
}

abstract class AbstractPet
{
  void sound ()
  {
    System.out.println ("eek");
  }
}

class Dog extends AbstractPet
{
  void sound ()
  {
    System.out.println ("Woof");
  }
}

class Cat extends AbstractPet
{
  void sound ()
  {
    System.out.println ("meow");
  }
}

Solution 4

Well, let's take Cat which is a subclass of the abstract class Animal.

You can cast Cat to Animal because a cat is an animal. It does everything a normal animal does, since it has the functions of an animal.

Subclassing an abstract class is the same. You can simply use "is a" because it's a subclass.

You can define a list of animals as a zoo, but it can have dogs and cats - after all, they're both animals.

Casting a Cat to an Animal doesn't actually make it less of a Cat than it was - you simply tell your code to treat it like it would treat any other animal.

Edit
In case you don't like cats (I don't either), let me redirect you to the Wikipedia article about inheritance. Abstract classes would be useless if you can't cast them.

Solution 5

Q: Can you cast to an abstract class?

A: Sure - of course you can.

What you can't do is call an abstract method of an abstract class. (inserting from comment section -Andrew Barber- below) -- You are actually calling the concrete implementation of it in the subclass.

Share:
21,982
user1125516
Author by

user1125516

Updated on July 05, 2022

Comments

  • user1125516
    user1125516 about 2 years

    I am actually reading a book about design patterns in java and I am a newbie :)

    http://www.amazon.com/Design-Patterns-Java-TM-Software/dp/0321333020/ at the chapter about composite pattern I came across a code that puzzles me, a cast to an abstract class, I have also not well understood what happens when the sub-clase calls the constructor of the abstract superclass, can you help me please!

    The cast that I am talking about is in the isTree(Set visited)

            MachineComponent c = (MachineComponent) i.next();
            if (visited.contains(c) || !c.isTree(visited)) 
    
          
    

    How can we call the isTree method of the subclass after a cast to his abstract superclass while the isTree superclass method is abstract?

    Here are snippets of the two classes:

    package com.oozinoz.machine;
    /*
     * Copyright (c) 2001, 2005. Steven J. Metsker.
     */
    
    import java.util.*;
    import com.oozinoz.iterator.ComponentIterator;
    
    /**
     * Objects of this class represent either individual machines or composites of
     * machines.
     */
    
    public abstract class MachineComponent {
    
        /*
         * Subclasses implement this to support the isTree() algorithm.
         */
    
        protected abstract boolean isTree(Set s);
     
        // rest of class omitted
    }
    

    2:

    package com.oozinoz.machine;    
    /*
     * Copyright (c) 2001, 2005. Steven J. Metsker.
     */
    
    import java.util.*;
    import com.oozinoz.iterator.ComponentIterator;
    import com.oozinoz.iterator.CompositeIterator;
    
     /**
     * Represent a collection of machines: a manufacturing line, a bay, or a
     * factory.
     */
    
    public class MachineComposite extends MachineComponent {
        protected List components = new ArrayList();
    
        /**
         * @param visited a set of visited nodes
         * @return true if this composite is a tree
         * @see MachineComponent#isTree()
         */
    
        protected boolean isTree(Set visited) {
            visited.add(this);
            Iterator i = components.iterator();
            while (i.hasNext()) {
                MachineComponent c = (MachineComponent) i.next();
                if (visited.contains(c) || !c.isTree(visited)) 
                    return false;
            }
            return true;
        }
    
        // rest of class omitted
    }
    
  • mre
    mre over 12 years
    Yeah...completely not true.
  • paulsm4
    paulsm4 over 12 years
    @wrscheider99 - Absolutely correct. And in fact that's the DEFINITION of an abstract class - it's a class for which you cannot create any concrete instances - for which you MUST subclass in ORDER to create a concrete instance. Frankly, "interfaces" tend to be much, much more useful in Java. But abstract classes are important in many cases, including the OP's example.
  • Paul
    Paul over 12 years
    @mre, what's not true about it? An abstract method has no code so what would you be calling?
  • Andrew Barber
    Andrew Barber over 12 years
    This is true, while I can see how some might not think so if they are nitpicking the terms differently than the answerer. If you think you are calling the abstract function, you are actually calling the concrete implementation of it in the subclass.
  • mre
    mre over 12 years
    @Paul, To me, this answer seemed to say that it was impossible to invoke an abstract method of an abstract class, which is not true at all.