开发者

What is the point of an abstract class?

I understand what an abstract class is in OOP paradigm. Yeah an abstract class is an incomplete type, cannot be instantiated.

Subclasses of the abstract class can extend the superclass and so on, and call a method through using a base type variable. But that is what I don't get.

I was reading the book, and the author said using a Superclass variable to reference a subclass and calling a common method calls the correct method. And yeah that's true. For example this little code I wrote:

public class ObjectOne extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectOne\n" ;
    }
}



public class ObjectTwo extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectTwo\n" ;
    }
}


public class ObjectThree extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectThree\n" ;
    }
}


public class SuperObject {
    public String objectString()
    {
        return "SuperObject" ;      
    }
}

    import static java.lang.System.out ;
public class ControlClass {

    public static void main(String[] args)
    {
        SuperObject [] arr = {new ObjectOne(), new ObjectTwo(), new ObjectThree()} ;

        for(SuperObject elem:arr)
        {
            out.println(elem.objectString()) ;
        }
    }
}

Em, so when main executes the correct methods are called for the objects using just the reference type. My question is so what is the point of an abstract class? Polymorphism works regardless of whether the method or class is abstract. Unlike C++, polymorphism works only when you specify it. For Java, it works apparently all the time.

So I guess the abstract keyword or abstract concept is just to complete the inheritance hierarchy, make incomplete types impossible to instantiate, or is to promote good OOP practice? Can someone 开发者_C百科clarify thanks.


I'm not sure you understand what an abstract class is, as none of the classes in your example are abstract, and nothing in there is an interface either. What you are doing is extending an instantiable class. Without the abstract keyword there is nothing to stop me doing:

SuperObject obj = new SuperObject();

I think a better example would be to illustrate how abstract classes are used. What they are commonly used to do is to provide a common method implementation. If a number of classes implement some interface, but all of them implement the same method in the same way using the same code, then what is commonly done is to create an abstract class that contains the common implementation, and get all of the concrete implementations to extend that class. This facilitates code reuse, and decreases the likelihood that one developer will change the common method implementation for one class, but forget the others. For example..

public class ObjectOne extends Thing {
  public String objectString()
  {
      return "objectString() of class ObjectOne\n" ;
  }
}

public class ObjectTwo extends Thing {
  public String objectString()
  {
    return "objectString() of class ObjectTwo\n" ;
  }
}

public class ObjectThree extends Thing {
  public String objectString()
  {
    return "objectString() of class ObjectThree\n" ;
  }
}

public abstract class Thing implements SuperObject {
  public String alwaysTheSame() {
    return "The same thing";
  }
}

public interface SuperObject {
  public String objectString();

  public String alwaysTheSame();
}

import static java.lang.System.out ;

public class ControlClass {

  public static void main(String[] args)
  {
    SuperObject [] arr = {new ObjectOne(), new ObjectTwo(), new ObjectThree()} ;

    for(SuperObject elem : arr)
    {
        out.println(elem.alwaysTheSame());
        out.println(elem.objectString()) ;
    }
  }
}

What we have done here is introduce an abstract class Thing, which provides a method implementation that is common to all 3 implementations of SuperObject (which is now an interface). This means we don't have to write the same code again in three different places in order to to fully implement the SuperObject interface in each one of our concrete classes.

In addition to this, you can also extend non final classes. You may wish to do this in order to override the default behaviour of one or methods on the concrete class, or to decorate the the class with additional methods. Of course, when you are designing a class hierarchy from scratch you don't stick concrete classes in it that then get extended by other classes, as it's generally considered a bad code smell. However, few of us work with totally new written-from-scratch codebases, and must adapt an exiting codebase to new requirements. Extending a concrete class is one tool in the toolbox to do this.

EDIT: Misunderstood what the OP was asking, but the last paragraph above is relevant.


Let's say you want to deploy an application on an Ipad, Android, Iphone and Desktop application. You work on an important part that will do 95% of the job in an abstract class. Then you create 4 other small classes that will implement the abstract method differently for each device.

That way, you won't repeat 95% of the work, and each device will instanciate his own class, that extends the abstract common class.


Abstract classes are an excellent way to create planned inheritance hierarchies. They're also a good choice for nonleaf classes in class hierarchies.

Here's a good detailed explanation: (extracted from here)

Choosing interfaces and abstract classes is not an either/or proposition. If you need to change your design, make it an interface. However, you may have abstract classes that provide some default behavior. Abstract classes are excellent candidates inside of application frameworks.

Abstract classes let you define some behaviors; they force your subclasses to provide others. For example, if you have an application framework, an abstract class may provide default services such as event and message handling. Those services allow your application to plug in to your application framework. However, there is some application-specific functionality that only your application can perform. Such functionality might include startup and shutdown tasks, which are often application-dependent. So instead of trying to define that behavior itself, the abstract base class can declare abstract shutdown and startup methods. The base class knows that it needs those methods, but an abstract class lets your class admit that it doesn't know how to perform those actions; it only knows that it must initiate the actions. When it is time to start up, the abstract class can call the startup method. When the base class calls this method, Java calls the method defined by the child class.


You also don't have to implement certain methods in abstract classes. You can decide what have to be declared in Subclasses and what you want declare in the Superclass.

Look at OutputStream for example:

public abstract void write(int i) throws IOException;

public void write(byte abyte0[]) throws IOException {
    write(abyte0, 0, abyte0.length);
}

public void write(byte abyte0[], int i, int j) throws IOException {
    if(abyte0 == null)
        throw new NullPointerException();
    if(i < 0 || i > abyte0.length || j < 0 || i + j > abyte0.length || i + j < 0)
        throw new IndexOutOfBoundsException();
    if(j == 0)
        return;
    for(int k = 0; k < j; k++)
        write(abyte0[i + k]);
}

You have an abstract write method (because you don't knwo where the OutputStream is going to) but all other extra write methods are not abstract and forwarded to this methods. So you only have to declare one method in the Subclass and have some methods "extra" without having to implement it in every Subclass.


You may want a class not to have any instances. For example assume you have a Person class and two classes derived from it Student and Teacher. In this case you may not want to have any objects created from Person class as it may not have any meaning for your program.


The "point" is to enforce a class hierarchy, potentially with some functionality provided by base class(es), and force some behavior to be implemented by sub-classes.


You would use an abstract class in cases where you do want to specify certain behaviour but don't want anybody to instatiate it directly but having to subclass it.


An abstract class can be full bodied or the skeleton for the subclass. You define your template in the abstract class and its left for the subclass to extend and implement the methods defined in the superclass.


So I guess the abstract keyword or abstract concept is just to complete the inheritance hierarchy, make incomplete types impossible to instantiate, or is to promote good OOP practice?

My answer is yes to everything that you said.


Along with what others have said, you may be using a library written by someone else, where you don't have access to the source code, but want to change it's behavior.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜