前言-
本文是为个人学习做的整理性质的笔记,肯定带有许多不妥的地方,仅供参考。
(第九章·接口 《Thinking in Java》)
接口与内部类为我们提供了一种将接口与实现分离的更加结构化的方法
正文-
抽象类:是普通类与接口之间的一种中庸之道。
抽象类的对象几乎没有任何意义,我们创建抽象类是希望可以通过这个通用接口操纵一系列类。
抽象方法:是一种不完整的方法,仅有声明而没有方法体。
如:abstract void fun();
两者关系:如果一个类中包含一个或者多个抽象方法,该类必须被限定为抽象的(否则编译器会报错)
※可以创建一个没有任何方法的抽象类。(就像练习2和4那样)
※(???)为什么这样做?考虑这样一种情况:如果一个类让其包含任何abstract方法都显得没有实际意义,而且我们也想要阻止产生这个类的任何对象,那么这样做就很有用了。
关于继承:如果从一个抽象类里继承的话,就必须为基类中提供的所有抽象方法提供方法定义。(当然,可以选择不做,那么导出,或者说是继承的类也必须是抽象的,请为她加上abstract关键字)
总结-
创建抽象类和抽象方法非常有用,因为他们可以使类的抽象性明确起来,并告诉用户和编译器打算怎样使用它们。抽象类还是很有用的重构工具,因为她们使得我们很容易地将公共方法沿着继承层次结构向上移动。
练习-
(个人练习,仅供参考)
1 public class Lianxi1 { 2 public static void main(String[] args) { 3 // TODO 自动生成的方法存根 4 Mouse mouse=new Mouse(); 5 Gerbil gerbil=new Gerbil(); 6 mouse.eat(1); 7 mouse.shout(2); 8 gerbil.eat(3); 9 gerbil.shout(4); 10 System.out.println(mouse.toString()+" "+gerbil.toString()); 11 System.out.println(mouse.what()+" "+gerbil.what()); 12 } 13 } 14 15 abstract class Rodent{ 16 public int count=0; 17 public abstract void eat(int i) ; 18 public abstract void shout(int i) ; 19 public String what() { 20 return "Rodent"; 21 } 22 @Override 23 public String toString() { 24 String s=this.getClass().toString(); 25 return s+" [count=" + count + "]"; 26 } 27 } 28 29 class Mouse extends Rodent{ 30 @Override 31 public void eat(int i) { 32 // TODO 自动生成的方法存根 33 count=i; 34 System.out.println(i+" Mouse eat"); 35 } 36 @Override 37 public void shout(int i) { 38 // TODO 自动生成的方法存根 39 count=i; 40 System.out.println(i+" Mouse shout"); 41 } 42 } 43 44 class Gerbil extends Rodent{ 45 @Override 46 public void eat(int i) { 47 // TODO 自动生成的方法存根 48 count=i; 49 System.out.println(i+" Gerbil eat"); 50 } 51 @Override 52 public void shout(int i) { 53 // TODO 自动生成的方法存根 54 count=i; 55 System.out.println(i+" Gerbil shout"); 56 } 57 }
public class Lianxi2 { public static void main(String[] args) { // TODO 自动生成的方法存根 // new Nothing(); 会报错 } } abstract class Nothing{ }
public class Lianxi3 { public static void main(String[] args) { // TODO 自动生成的方法存根 new DoSth(); } } abstract class AbsPrint{ abstract void print() ; } class DoSth extends AbsPrint{ private int output=233; public DoSth() { // TODO 自动生成的构造函数存根 this.print(); } @Override void print() { // TODO 自动生成的方法存根 System.out.println(output); } }
public class Lianxi4 { public static void useBase(Base base) { //创建一个静态方法,它可以接受指向基类的引用,将其向下转型到导出类,然后再调用该静态方法 Exbase eb=(Exbase)base; eb.saySth(); } public static void useBase2(Base2 base2) { //没有必要向下转型 Exbase2 eb=(Exbase2)base2; eb.saySth(); } public static void main(String[] args) { // TODO 自动生成的方法存根 Base b1=new Exbase(); useBase(b1); // b1.saySth(); Base中不存在saySth()方法! Base2 b2=new Exbase2(); // useBase2(b2); 没有必要向下转型 b2.saySth(); } } abstract class Base{ //创建一个不包含任何方法的抽象类。 } class Exbase extends Base{ //从Base中导出一个类,并添加一个方法 void saySth() { System.out.println("exbase say"); } } abstract class Base2{ //将基类方法加上abstract声明 abstract void saySth(); } class Exbase2 extends Base2{ void saySth() { System.out.println("exbase2 say"); } }