-
Java
中的
abstract
方法和
abstract
类的问题
当知道一个类的子类将不同的实现某个方法时,
把该类声
明为抽象类很有用,
可以共用相同
的父类方法,不必再定义。<
/p>
抽象类和抽象方法的关系
:
含有抽象方法的类一定是抽象类,
抽象类里不一定含有抽象方法。
抽象类存在的意义是用来被继承的。
一个类继
承了一个抽象类,
必须实现抽象类里面所有的
抽象方法,否则,
此类也是抽象类。
abstract
修饰符用来修饰类和成员方法
1
:
用
abstract
修饰的类表示抽象类,抽象类位于继承树的
抽象层,抽象类不能被实例化。
2
:
用
abstract
修饰的方法表示抽象方法
< br>,
抽象方法没有方法体。抽象方法用来描述系统具有
什么
功能,但不提供具体的实现。
abstract
规则:
1
:抽象类可以没有抽象方法,但是有抽象方法的类必须定义为抽象类,
如果一个子类继承
一个抽象类,
子类没有实现父类的所有抽象方
法,
那么子类也要定义为抽象类,
否则的话编
< br>译会出错的。
2
:抽象类没有
构造方法,也没有抽象静态方法。但是可以有非抽象的构造方法
3
:抽象类不能被实例化,但是可以创建一个引用变量,类型是一个抽象类,并让它引
用非
抽象类的子类的一个实例
4
:不能用
final
修饰符修饰
Q:java
里面有抽象类么?和接口的区别是什么?
<
/p>
A:java
中有抽象类
,
用关键字
abstract
修饰。
< br>
以下是我对这个问题的看法。
首先,从语法上讲,抽象类是一个类,根据
java
的单继承
体系。如果它有子类,那么它的
子类只能继承它。
java
允许实现多个接口。所以一个类可以实现多个接口
抽象类里面可以定义各种类型和访问权限的变量
(<
/p>
就像普通类一样
)
,
也可以定义各种访问权
限的方法
(
就像普通类一样
)
。
但是接口不可以。在接口里面定义的方法默认就是
public
abstract
的,变量默认就是
p
ublic
static final
的。
< br>(
不管你有没有加权限控制符,不加,默认就是这些权限;加错了,权限缩小
p>
了,那么就会报错
)
其次,
从意义上讲,
如果继承一个抽象类,那么抽象类和它的子类就有父子关系,<
/p>
即有类的
层次关系
(
这关系到类的设计问题
)
。
p>
接口,在我看来,是一种契约或者协议,是一层提供给另一层的接口
(
可以想象成
OSI
各层
之间的关系
)
在某一层中有多个类协作实现这个层
的功能,
通过接口暴露出去。
但这些类之间会有层次关
系
(is a,has a)
Q:
一个方法加
abstract
和不加
abstract
有什么区别?就是说不加有什
么关系?加了又会怎
样?
A:
一方法要是加
abstract
,那么这个方
法就是抽象的,须由子类去实现
抽象方法必须在抽象类当中,
也就是说,
一个类只要有一个方法是抽象的,
< br>那么这个类就必
须是抽象类
抽象类里面的方法不一定要抽象的,也可以全都不是抽象的
抽象类不能实例化!
所以可以想到,
当你不想让你的类被别人实例化,
只想这个类的子类可以实例化
,
那么只要
将这个类声明为
abstr
act
的就可以了
(
和
final
的情况蛮相近,
当你不想让这个类再有子类化,
只要在类的声明前面添加
fin
al
即可
)
不过更多的情况下,我想
,还是一个抽象类,他既有部分抽象方法,也有部分具体的方法。
具体的方法是已经定义好的,抽象方法需要由子类去实现。
(
个人感觉和
C++
的
virtual
很相
近
,
不过
abstract
是纯虚的
)
那么为什么要有抽象类呢?我说过这关系到你类的设计问题
。
(
当然还有不想被实例化
)
譬如经常举的一个例子
abstract class Shape{
public abstract void
draw();
public abstract void reDraw();
}
class Triangle extends Shape{
public void
draw(){...}
public void reDraw(){...}
}
class Circle
extends Shape{
public void draw(){...}
public void
reDraw(){...}
}
当然你可以这样设计
class
Shape{
public void draw(){}
public void reDraw(){}
}
这样设计有
2
个不妥之处
:
1.
不符合逻辑。
Shape
是你针对具体的事物
p>
(Triangle,Circle)
抽象出来的。它定义的方法应
该
到子类中去实现
2.
在设计的时候就应该认识到,
实例化
Shape
p>
是没有意义的,
因为
Shape
本身只是一种抽象。
现在别人如果拿来就可以实例化了,
< br>这样的操作方式违背了当初设计的意愿。
而且会存在潜
在
的危险。
(
当前的实现可能看不出危险
)
那么,如果把
Shape
定义成<
/p>
Interface
呢?
当然可以
Interface
Shape{
void
draw();
void
reDraw();
}
class Triangle implements Shape{
public void
draw(){...}
public void reDraw(){...}
}
class Circle
implements Shape{
public void draw(){...}
public void
reDraw(){...}
}
只不过现在子类
Triangle
,
C
ircle
和
Shape
之间的关系就
不是父子了。
这样设计其实违背了常理,
因为在我们的观念中,
Triangle
和
Circle
本来就应该是一种
Shape
而不应该是他们都遵守一定的操作方式
(void
draw(),void reDraw())
如何扩展这些设计呢?譬如说为
Triangle
和
Circle
添加
erase
方法?
如果是
class
Shape
这样的设计,很简单,只要
abstract class Shape{
public abstract void
draw();
public abstract void reDraw();
public void
erase(){
Window window=rentWindow();
();
}
}
Triangle
和
Circle
的代码可以原封不动!
你可能会问,为什么不把
erase()
设计成为<
/p>
abstract
的。你当然可以把
er
ase()
设计成
abstract
的
,然后在子类中重写这个方法,提供子类自己的实现。
但是,
在现实当中,你可能更赞同是用上面的设计。的确,
erase
方法只要简单的进行擦除
就可以了,不是吗?
这样一来,扩展就变的很容易了。