2016-05-15 109 views
-1

我们可以去抽象类和我们可以去方法重写的场景。 让我解释一下。 我有一个类A.抽象方法优于方法重写的好处

abstract class A { 
    abstract public void display(); 
} 

和在通常情况下,我可以扩展这个类作为

class B extends A { 
    public void display() { 
     System.out.println("This is a bike"); 
    } 
} 

相同的这一点,我可以通过使用方法覆盖特征,即使做类A的方法有一些东西。

所以我的问题是,我应该什么时候抽象类,当我可以通过方法重写实现相同的功能。

+0

是不是使用抽象类的主要好处,你不能实例化它们(如接口),但可以提供基础构造函数和扩展其他类(如类)? – mezzodrinker

+0

我不明白你的问题:如果你有抽象方法的抽象类,你将不得不在子类中覆盖它。 – hotzst

+0

你已经有方法在这里覆盖,因为你重写了显示方法 – Igorock

回答

0

抽象类是至少有一个抽象方法的类。这是一个没有在这个类中实现的方法,但必须由派生类来实现。

应该使用抽象类来表示抽象概念。你不能从抽象类创建对象,它们只用于从它们派生具体的类。其实,我的观点是抽象类在大多数情况下是没有意义的。您应该使用接口。

+1

“一个抽象类是一个至少有一个抽象方法的类,这是一个没有在这个类中实现但是必须由派生类实现的方法。这是不正确的。在C++中你会是对的,但是[在Java中你可以声明一个类抽象,即使它没有抽象方法](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html)。 – Turing85

+0

@图灵85:你可以,但是,是吗? –

+1

[当然](http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServlet.html)。 – Turing85

1

抽象类/方法的要点是为多态使用提供一个基类型。换句话说,你有一些基本类型A,其他人将扩展来提供一些操作。您不关心确切的实施,但您希望该操作可用。

一个经常被引用的例子是一个形状类:

abstract class Shape { 
    public abstract void draw(); 
} 
class Circle extends Shape { 
    int radius; 
    // Constructors, etc. 
    @Override 
    public void draw() { 
     System.out.println("Circle of radius " + radius); 
    } 
} 
class Square extends Shape { 
    int side; 
    // Constructors, etc. 
    @Override 
    public void draw() { 
     System.out.println("Square of side " + radius); 
    } 
} 

类形状是指任何形状的方式。你知道不能有Shape类的实例,但是你仍然可以有一个Shape[]或一个List<Shape>。这样一来,你可以使用它像这样:

void drawAll(Iterable<? extends Shape> shapes) { 
    for (final Shape s : shapes) 
     s.draw(); 
} 

如果你没有一个抽象基类Shape,你就不能写这个方法;你会写一个圆对象的列表,另一个用于广场对象的列表 - 甚至这种解决办法仍然不会允许你这样做:

List<Shape> ls = Arrays.asList(new Circle(7), new Square(5)); 
drawAll(ls); 
+0

这不完全正确。尽管'Shape'和它的'draw()'方法不是抽象的,所有这些都是可能的。主要的好处是你强制每一个Shape类的子类重写'draw()'或抽象自己。你不能(轻易地)强制执行现有方法的覆盖。 – Turing85

+0

@ Turing85确实......我的观点是Shape超过_not_的优势(因此只有一系列“无关”的类和draw方法)。在不实际使用关键字的情况下,“抽象”的“最接近的东西”是让Shape.draw()引发一个异常,所以任何有用的实现都必须覆盖它。 –

+0

你不能声明没有body的'draw'方法;你需要将它声明为抽象:'public abstract void draw();'。 –

0

首先第一件事情:抽象方法eoncorporate覆盖。从这个意义上说,你的问题有些不合时宜。

我们在房间里的熊:在你的榜样,你给示例类AB

abstract class A { 
    abstract public void display(); 
} 

class B extend A { 
    @Override 
    public void display(){ 
     System.out.println("This is a bike"); 
    } 
} 

我加入了@Override注释furhter强制执行的概念,抽象使用压倒一切。如果display()A不会是absatract,那么您不会有任何(容易)的可能性来执行A的每个子类都有一个方法display()。您当然可以在A内执行display()

但是在某些情况下,这可能是不可能的,因为您没有足够的信息来编写有问题的方法。以一些列表的get(int index)方法为例。 getter的实现在很大程度上取决于列表的实现(访问ArrayList作品的第100个元素与访问LinkedList的第100个元素基本不同)。但是你确定每个列表应该总是有这个方法。所以,你使这个方法抽象为。总结:在一个完美的世界里,每个程序员都会写和读文档,你可能不需要抽象方法。但我们都是人类(即我们没有阅读每一行文件,我们犯了错误/忘记了事情),因此对这种错误有一定的保护是很好的。此外,使用空方法并期望用户覆盖它们以使您的程序/库可以工作是违反直觉的。


旁注:实际上List是一个接口,不是类。我仅将此示例用于演示目的。