本章目录
抽象类
1、抽象类和抽象方法的定义
抽象类:使用 abstract 关键字修饰的类。
抽象类是它所有子类共有成员的集合,是包含一个或多个抽象方法的类,它进一步描述了多个具体类的公共属性和行为,可以看作是对多个类抽象的结果。
抽象类的作用在于将许多有关的类组织在一起,得出一个公共的类,被组织在一起的类作为从公共类派生出的子类,抽象类刻画了共有属性和行为,并通过继承机制传送给它的派生类。
抽象方法:使用 abstract 关键字修饰的,没有方法体的方法。
抽象方法没有方法体是为了便于子类对其进行重写。
抽象类和抽象方法格式:
//抽象类
abstract class 类名{
//抽象方法
}
//抽象方法
public abstract void 方法名();
2、抽象类成员特点:
成员变量:可以是变量,也可以是常量。
构造方法:有。抽象类有成员变量,需要构造方法来进行初始化,并且子类实例化对象时,依旧满足先执行父类构造后执行子类构造的顺序。
成员方法:可以是抽象方法,可以是非抽象方法。所以抽象类中不一定写抽象方法,但写了抽象方法的类一定是抽象类。
3、抽象类使用原则
- 抽象类和抽象方法都必须使用 abstract 关键字修饰。
- 抽象类不能用 final 修饰,因为抽象类要被继承,而 final 修饰的类无法被继承。
- 抽象类不能直接实例化,需要依靠子类向上转型的方式处理。
- 抽象类的子类要么是抽象类,要么重写抽象类中所有的抽象方法。
- 抽象方法必须用 public 或 protect 修饰,因为如果使用 private 修饰,子类无法继承该方法,就不能重写。
4、抽象类与普通类的区别
- 抽象类的子类有明确要求重写抽象类中所有抽象方法,普通类可以自选是否需要重写父类方法。
- 抽象类仅仅比普通类多了抽象方法,其他组成部分和普通类完全一致。
- 抽象类的实例化需要依靠子类向上转型,普通类可以直接实例化。
5、抽象类案例(模板设计模式)
现有三类事物:
1、机器人:充电,工作。
2、人:吃饭,睡觉,工作。
3、猪:进食,睡觉。
需求:设计一个程序,实现三种不同事物的行为。
创建抽象行为类:
public abstract class Action {
public static final int EAT = 1;
public static final int SLEEP = 3;
public static final int WORK = 5;
public abstract void eat();
public abstract void sleep();
public abstract void work();
public void commond(int flag){
switch (flag){
case EAT:
this.eat();
break;
case SLEEP:
this.sleep();
break;
case WORK:
this.work();
break;
default:
break;
}
}
}
创建机器人类:
public class Robot extends Action{
@Override
public void eat() {
System.out.println("机器人充电");
}
@Override
public void sleep() {
}
@Override
public void work() {
System.out.println("机器人工作");
}
}
创建人类:
public class Human extends Action{
@Override
public void eat() {
System.out.println("人吃饭");
}
@Override
public void sleep() {
System.out.println("人睡觉");
}
@Override
public void work() {
System.out.println("人工作");
}
}
创建猪类:
public class Pig extends Action{
@Override
public void eat() {
System.out.println("猪进食");
}
@Override
public void sleep() {
System.out.println("猪睡觉");
}
@Override
public void work() {
}
}
测试类:
public class Test {
public static void main(String[] args) {
new Test().function(new Robot());
System.out.println("=====================");
new Test().function(new Human());
System.out.println("=====================");
new Test().function(new Pig());
}
public void function(Action action){
action.commond(Action.EAT);
action.commond(Action.SLEEP);
action.commond(Action.WORK);
}
}
所有子类如果想正常完成操作,必须按照指定的方法进行重写,这时,抽象类就起模板的作用。
接口
1、接口理解
1)接口是一组规则的集合,它体现了实现了接口的类或接口所具备的本领。类似于自然界中“如果你是…则你能…”的理念。
例如:在自然界中,人们都具备进食这项本领,即“如果你是人,则你能进食”。那么模拟到程序中,应该有一个IPerson 接口,接口中有一个方法叫 eat(),然后规定,人类必须实现 IPerson 接口,这就模拟了自然界中“如果你是人,则你能进食”这条规则。
2)接口是在一定细粒度上同类事物的抽象表示。注意这里强调了在一定细粒度上,因为“同类事物”这个概念是相对的,它因细粒度不同而不同。
例如:在我眼里,我是一个人,我和猪有本质区别,我可以接收我和我同学是同类这一说法,但绝不能接收我和猪是同类这一说法。但是,在动物学家眼里,我和猪就是同类,因为我们都是动物,他认为我和猪都实现了 IAnimal 这个接口,而他在研究动物行为时,不会把我和猪分开对待,而会从“动物”这个较大的粒度上进行研究,但他会认为我和一棵树有本质的区别。
现在换了一个遗传学家,情况又不同了,因为生物都能遗传,所以在他眼里,我不仅和猪没有了区别,我和一棵树,一个蘑菇,乃至一个 SARS 病毒都没什么区别,他认为我们都实现了 IDescendable (descend vi. 遗传)这个接口,即我们都是可遗传的东西,他不会分开研究我们,而会将所有生物作为同类进行研究,在他眼里没有人和病毒之分,只有可遗传和不可遗传的物质。但至少,我和一块石头还是有区别的。
不幸的事情发生了,某日,地球上出现了一位伟人,他叫列宁,他在熟读马克思恩格斯唯物辩证主义思想巨著后,颇有心得,于是他下了一个著名的定义:所谓物质,就是能被意识所反映的客观存在。至此,我和猪,和树,和石头,已经没什么区别了,因为在列宁眼里,我们都是可以被意识反应的客观存在,我们都实现了 IEsse(esse n.客观存在)接口,可以归为同类研究。
这正是接口存在的意义,面向对象思想的核心之一是多态,什么叫多态性?说白了就是在某个细粒度上对同类事物不加区别的对待而统一处理。之所以能这样所,就是因为接口的存在,像遗传学家,他明白所有生物都实现了 IDescendable 这个接口,那只要是生物,就有 Descend() 这个方法,于是他可以统一研究,而不至于分别去研究每一种生物。
2、接口定义
接口:由没有方法体的方法组成的集合体,用 interface 关键字表示。
定义格式:
interface 接口名{
public void method1();
public void method2(String para1,int para2);
...
}
2、接口成员特点
成员变量:只能是静态常量,使用 public static final 修饰,当定义为普通变量时,系统编译时会默认编译为静态常量。
构造方法:接口没有构造方法。
成员方法:只能是抽象方法,可以省略 abstract,系统在编译时会默认加上。
4、类与接口的关系
类与接口之间是实现关系,用 implement 关键字表示。
格式:
interface 接口名{
//方法
}
public class 类名 implement 接口名{
//重写接口中的方法
}
类与类之间是继承关系,只支持单继承,可以多层继承。
类与接口之间是实现关系,一个类可以实现多个接口。
接口与接口之间是继承关系,一个接口可以继承多个接口。
5、抽象类和接口的区别
成员变量 | 构造方法 | 成员方法 | |
---|---|---|---|
抽象类 | 变量,常量 | 有 | 抽象,非抽象 |
接口 | 常量 | 无 | 抽象 |
6、接口案例
猫狗类实现跳跃功能。
抽象动物类:
public abstract class Animal {
public String name;
public int age;
public abstract void eat();
public abstract void sleep();
}
跳跃接口:
public interface Jump {
public void jumpStudy();
}
猫类:
public class Cat extends Animal implements Jump{
@Override
public void eat() {
System.out.println("猫吃小鱼干");
}
@Override
public void sleep() {
System.out.println("猫在阳台睡觉");
}
@Override
public void jumpStudy() {
System.out.println("猫跳上了衣柜");
}
}
狗类:
public class Dog extends Animal implements Jump{
@Override
public void eat() {
System.out.println("狗吃大骨头");
}
@Override
public void sleep() {
System.out.println("狗在客厅睡");
}
@Override
public void jumpStudy() {
System.out.println("狗跳上了沙发");
}
}
测试类:
public class TestAnimal {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "加菲";
cat.age = 1;
cat.eat();
cat.sleep();
cat.jumpStudy();
System.out.println("===================");
Dog dog = new Dog();
dog.name = "大黄";
dog.age = 3;
dog.eat();
dog.sleep();
dog.jumpStudy();
}
}
今晚月色来的真巧,趁四野无人偷她一笑.
各位看官,接口与抽象类就到这里啦,下篇见(∩_∩)~~
-Czx.