1. 抽象类的定义与使用
1.1 抽象类的定义与使用
抽象类只是在普通类的基础上扩充了一些抽象方法而已,所谓的抽象方法指的是只声明而未实现的方法(即没有方法体)。所有抽象方法要求使用abstract关键字来定义,并且抽象方法所在的类也一定要使用abstract关键字来定义,表示抽象类。
范例:定义一个抽象类
abstract class Person{
private String name ; // 属性
public String getName(){ // 普通方法
return this.name;
}
public void setName(String name){
this.name = name ;
}
// {}为方法体,所有抽象方法上不包含方法体
public abstract void getPersonInfo() ; //抽象方法
}
通过上述代码我们会发现,抽象类就是比普通类多了一些抽象方法而已。
抽象类中包含有抽象方法,而抽象方法不包含方法体,即没有具体实现。
1.2.抽象类的使用限制
a.所有抽象类必须有子类 (final与abstract不能同时出现) (final:类不能被继承,abstract:必须被继承,两者矛盾。)
b.抽象类的子类必须覆写所有抽象方法 (或者子类也使用abstract关键字定义)
priavte与abstract不能同时出现,抽象方法必须被覆写而privtae方法无法被覆写。
c.抽象类无法直接产生实例化对象,但可以通过子类向上转型进行实例化。
且子类依然遵循对象实例化流程,先调用抽象类构造方法而后再调用子类构造。
d.抽象类可以没有抽象方法,但是此时仍然不能直接实例化对象。
范例:使用抽象类
abstract class Person{
private String name ; // 属性
public String getName(){ // 普通方法
return this.name;
}
public void setName(String name){
this.name = name ;
}
// {}为方法体,所有抽象方法上不包含方法体
public abstract void getPersonInfo() ; //抽象方法
}
class Student extends Person{
public void getPersonInfo(){
System.out.println("I am a student");
}
}
public class Test{
public static void main(String[] args) {
Person per = new Student() ; //实例化子类,向上转型
per.getPersonInfo() ; //被子类所覆写的方法
}
}
2. 接口
开发原则:接口优先原则,在一个场景既可以使用抽象类也可以使用接口的时候,优先考虑使用接口。
2.1定义:
接口中只有全局常量和抽象方法(JDK8之前),接口使用interface定义接口
interface IMessage{
public static final String MSG = "hello" //全局常量
public abstract void getMsg(); //抽象方法
}
2.2使用原则:
a.接口无法直接创建实例化对象,需要通过具体子类向上转型为其实例化。
b.接口命名一般以 I 开头,子类使用implements关键字实现接口,一般以impl结尾,表示此类是一个接口的子类。
c.接口允许多实现(多继承),一个子类可以同时使用implements实现若干个接口。
d.接口中只允许public权限!即便不写,也是public。接口中abstract、final、static均可以省略不写。接口中的方法和属性不要加任何修饰符号,public也不要加,保持代码的简洁性。
e.当子类既需要继承抽象类又需要实现接口时,先extends一个抽象类而后使用implements实现多个接口。
f.抽象类可以使用implements实现多个接口,接口(一定)不能继承抽象类,接口可以使用extends继承多个父接口。
范例:观察子类实现接口&父接口间的相互转换
interface IMessage{
public static final String MSG = "I am a message" ; // 全局常量
public abstract void print() ; // 抽象方法
}
interface INews {
public abstract String getNews() ;
}
class MessageImpl implements IMessage,INews {
public void print() {
System.out.println(IMessage.MSG) ;
}
public String getNews(){
return IMessage.MSG ; // 访问常量都建议加上类名称
}
}
public class Test{
public static void main(String[] args) {
IMessage m = new MessageImpl() ; //子类向上转型,为父接口实例化对象
m.print() ; // 调用被子类覆写过的方法
INews n = (INews) m ;
System.out.println(n.getNews()) ;
}
}
***当一个子类即需要实现接口又需要继承抽象类时,请先使用extends继承一个抽象类,而后使用implements实现多个接口。
范例:子类继承抽象类和实现接口。
interface IMessage {
public void print() ;
}
abstract class News {
// 抽象类中方法前面的abstract不能省略,否则就是普通方法
public abstract void getNews() ;
}
class MessageImpl extends News implements IMessage {
public void print() {
System.out.println("I am a message") ;
}
public void getNews() {
System.out.println("I am News") ;
}
}
public class Test{
public static void main(String[] args) {
IMessage m = new MessageImpl() ;
m.print() ;
// MessageImpl是抽象类和接口的共同子类
News news = (News) m ;
news.getNews() ;
}
}
***一个抽象类可以使用implements实现多个接口,但是接口不能继承抽象类。
范例:抽象类实现接口
interface IMessage {
public void print() ;
}
abstract class News implements IMessage{
//News为抽象类,可以不实现IMessage中的抽象方法
// 抽象类中方法前面的abstract不能省略,否则就是普通方法
public abstract void getNews() ;
}
class MessageImpl extends News {
public void print() {
System.out.println("I am a message") ;
}
public void getNews() {
System.out.println("I am News") ;
}
}
public class Test{
public static void main(String[] args) {
IMessage m = new MessageImpl() ;
m.print() ;
// MessageImpl是抽象类和接口的共同子类
News news = (News) m ;
news.getNews() ;
}
}
***一个接口可以使用extends继承多个父接口。
interface A {
public void printA() ;
}
interface B {
public void printB() ;
}
interface C extends A,B { // 接口多继承
public void printC() ;
}
class Impl implements C{
public void printA() {}
public void printB() {}
public void printC() {}
}
public class Test{
public static void main(String[] args) {
}
}
3.抽象类与接口的区别
除了单继承的局限之外,实际上使用抽象类和接口都是类似的。在实际开发中,抽象类的设计比接口复杂。