抽象类有什么意义?

时间:2011-10-11 14:56:17

标签: java

我理解OOP范例中的抽象类是什么。是的抽象类是不完整的类型,无法实例化。

抽象类的子类可以扩展超类等,并通过使用基类型变量调用方法。但这是我没有得到的。

我正在读这本书,作者说使用Superclass变量来引用一个子类,并且调用一个公共方法调用正确的方法。是的,这是真的。例如,我写的这个小代码:

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,所以当main执行时,只使用引用类型为对象调用正确的方法。我的问题是抽象类的重点是什么?无论方法或类是抽象的,多态性都可以工作。 与C ++不同,多态性仅在 时指定它。对于Java来说,它显然一直很有效。

所以我猜抽象关键字或抽象概念只是为了完成继承层次结构,使不完整的类型无法实例化,或者是为了促进良好的OOP实践?有人可以澄清谢谢。

10 个答案:

答案 0 :(得分:11)

我不确定你理解抽象类是什么,因为你的例子中没有一个类是抽象的,也没有任何接口。你正在做的是扩展一个可实例化的类。没有abstract关键字,没有什么可以阻止我这样做:

  

SuperObject obj = new SuperObject();

我认为更好的例子是说明如何使用抽象类。他们通常习惯做的是提供常用方法实现。如果许多类实现了一些接口,但是它们都使用相同的代码以相同的方式实现相同的方法,那么通常做的是创建一个包含公共实现的abstract类,并获取所有扩展该类的具体实现。这有助于代码重用,并降低了一个开发人员改变一个类的通用方法实现的可能性,但忘记了其他类。例如..

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()) ;
    }
  }
}

我们在这里做的是介绍一个abstractThing,它提供了SuperObject(现在是一个接口)的所有3个实现共有的方法实现。这意味着我们不必在三个不同的地方再次编写相同的代码,以便在每个具体类中完全实现SuperObject接口。

除此之外,您还可以extendfinal课程。您可能希望这样做是为了覆盖具体类中的一个或多个方法的默认行为,或者使用其他方法来修饰该类。当然,当你从头开始设计一个类层次结构时,你不会在其中粘贴具体的类,然后由其他类扩展,因为它通常被认为是糟糕的代码味道。但是,我们很少有人使用全新的写入式代码库,并且必须使现有的代码库适应新的需求。扩展具体类是工具箱中的一个工具来执行此操作。

编辑:误解了OP的要求,但上面的最后一段是相关的。

答案 1 :(得分:4)

抽象类是创建计划继承层次结构的绝佳方法。对于类层次结构中的非叶类,它们也是一个很好的选择。

以下是一个很好的详细解释:(摘自here

  

选择接口和抽象类不是一个/或命题。如果您需要更改设计,请将其设为界面。但是,您可能具有提供某些默认行为的抽象类。抽象类是应用程序框架内的优秀候选者。

     

抽象类可以让你定义一些行为;他们强迫你的子类提供其他人。例如,如果您有应用程序框架,则抽象类可以提供默认服务,例如事件和消息处理。这些服务允许您的应用程序插入您的应用程序框架。但是,有一些特定于应用程序的功能,只有您的应用程序才能执行。此类功能可能包括启动和关闭任务,这些任务通常取决于应用程序。因此,抽象基类可以声明抽象关闭和启动方法,而不是尝试自己定义该行为。基类知道它需要那些方法,但是抽象类允许你的类承认它不知道如何执行这些操作;它只知道它必须启动行动。在启动时,抽象类可以调用启动方法。当基类调用此方法时,Java会调用子类定义的方法。

答案 2 :(得分:2)

您也不必在抽象类中实现某些方法。您可以决定在子类中声明的内容以及您希望在超类中声明的内容。

以OutputStream为例:

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]);
}

你有一个抽象的写方法(因为你没有知道OutputStream的位置)但是所有其他额外的写方法都不是抽象的并且转发给这个方法。因此,您只需要在子类中声明一个方法,并使某些方法“额外”,而不必在每个子类中实现它。

答案 3 :(得分:1)

您可能希望某个课程没有任何实例。 例如,假设您有一个Person类和两个派生自Student和Teacher的类。在这种情况下,您可能不希望从Person类创建任何对象,因为它可能对您的程序没有任何意义。

答案 4 :(得分:1)

假设您要在 Ipad Android Iphone 桌面应用程序上部署应用程序。 你在一个重要的部分工作,将在抽象类中完成 95%的工作。然后创建另外4个小类,为每个设备实现不同的抽象方法。

这样,你不会重复95%的工作,每个设备都会实现自己的类,扩展抽象的公共类。

答案 5 :(得分:0)

“要点”是强制执行类层次结构,可能具有基类提供的某些功能,并强制某些行为由子类实现。

答案 6 :(得分:0)

如果想要指定某些行为但希望任何人直接对其进行实例化但必须将其子类化,则会使用抽象类。< / p>

答案 7 :(得分:0)

抽象类可以是完整体,也可以是子类的骨架。您可以在抽象类中定义模板,在左侧为子类定义模板,以扩展和实现超类中定义的方法。

答案 8 :(得分:0)

  

所以我猜抽象关键字或抽象概念只是为了完成继承层次结构,使不完整的类型无法实例化,或者是为了促进良好的OOP实践?

我对你所说的一切都是

答案 9 :(得分:0)

与其他人所说的一样,您可能正在使用其他人编写的库,您无法访问源代码,但希望更改其行为。