继承,接口和抽象类
Gary
继承
继承Inheritance是继承是面向对象软件技术当中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
面向对象语言相比于面向过程的编程语言最突出的特点就是变量类型的继承
example:平行四边形为多边形,男人是人类,但是,一般来说,狗继承一个人这是不合理的,继承应该为是的关系,而不是有的关系(男人是人类,但女生是男生?显然错误)
code:
public class Human {
public int height;
public int weight;
public void eat(){
};
}
public class Man extends Human {
public void plough(){
};//耕田
}
//Man继承了Human有Human的属性和方法
继承的访问权限
1、private修饰词,表示成员是私有的,只有自身可以访问;
2、protected,表示受保护权限,体现在继承,即子类可以访问父类受保护成员,同时相同包内的其他类也可以访问protected成员。
3、无修饰词(默认),表示包访问权限(friendly, java语言中是没有friendly这个修饰符的,这样称呼应该是来源于c++ ),同一个包内可以访问,访问权限是包级访问权限;
4、public修饰词,表示成员是公开的,所有其他类都可以访问;
特点
- 单根继承原则:每个类只能继承一个类
- 不写extends都默认继承Java.lang.Object类,Java所有类都从它那里构建出一个类型的继承树
- Object类的默认方法有 clone,equals,finalize,getClass,hashCode,toString等方法
- 每个Java类都要有一个构造函数
- 若没有显示的构造函数就调用默认构造函数
- 没给子类构造函数的第一句话都是默认调用父类的第一个默认无参数构造函数super(),除非子类的构造函数第一句话是super。不会出现两条super()语句的
/**
* Authored by Gary on 2020/09/23.
**/
public class Human {
int height;
int weight;
public void eat(){
};
public Human(int height, int weight) {
this.height = height;
this.weight = weight;
}
}
/**
* Authored by Gary on 2020/09/23.
**/
public class Man extends Human {
public void plough(){
};//耕田
public Man(int height, int weight) {
super(height, weight);
}
}
抽象类
一个完整的类:所有方法都有实现(也可以一个方法都没有)
如果一个类有方法暂时没能实现,应该把它定义为抽象类,方法可在子类当中实现
/**
* Authored by Gary on 2020/09/23.
**/
public abstract class Animal {
int size;
String color;
public abstract void cal();
public void test(){
}
}
/**
* Authored by Gary on 2020/09/23.
**/
public class Cat extends Animal{
@Override
public void cal() {
System.out.println("Cal the cat");
}
}
接口 Interface
类的所有方法都没有实现,那么这个类就算是接口
- 接口不算是类
- 类可以继承一个类,但是可以实现(implements)多个接口2,继承和实现可以同时进行
定义规范
interface A{
//定义一个接口
public static final String MSG = "hello";//全局常量
public abstract void print();//抽象方法
}
由于接口里面存在抽象方法,所以接口对象不能直接使用关键字new进行实例化。接口的使用原则如下:
(1)接口必须要有子类,但此时一个子类可以使用implements关键字实现多个接口;
(2)接口的子类(如果不是抽象类),那么必须要覆写接口中的全部抽象方法;
(3)接口的对象可以利用子类对象的向上转型进行实例化。
package com.wz.interfacedemo;
interface A{
//定义一个接口A
public static final String MSG = "hello";//全局常量
public abstract void print();//抽象方法
}
interface B{
//定义一个接口B
public abstract void get();
}
class X implements A,B{
//X类实现了A和B两个接口
@Override
public void print() {
System.out.println("接口A的抽象方法print()");
}
@Override
public void get() {
System.out.println("接口B的抽象方法get()");
}
}
public class TestDemo {
public static void main(String[] args){
X x = new X();//实例化子类对象
A a = x;//向上转型
B b = x;//向上转型
a.print();
b.get();
}
}
运行结果
接口A的抽象方法print()
接口B的抽象方法get()
子父类之间的转换
- 向上转换是安全的
- 向下转换是不安全的
契约设计
Java编程准寻契约精神
契约:规定了对象应该包含的行为方法
接口定义了方法的名称,参数和返回值,规范了派生类的行为
基于接口,利用转型和多态,不影响真正方法的调用,成功将调用类和别调用类解耦
Summary
- 类转型:子类可以转换为父类,父类不可以转换为子类
- 多态:子类转型为父类后,调用普通方法,依旧子类的方法
- 契约设计:类不会直接使用另外一个类,而是采用接口的形式,外部可以“空投”这个接口下的任意子类对象
public interface Animal {
public void eat();
public void move();
}
public class AnimalTest {
public static void haveLunch(Animal a) {
a.eat();
}
public static void main(String[] args) {
Animal[] as = new Animal[4];
as[0] = new Cat();
as[1] = new Dog();
as[2] = new Cat();
as[3] = new Dog();
for(int i=0;i<as.length;i++) {
as[i].move(); //调用每个元素的自身的move方法
}
for(int i=0;i<as.length;i++) {
haveLunch(as[i]);
}
haveLunch(new Cat()); //Animal a = new Cat(); haveLunch(a);
haveLunch(new Dog());
haveLunch(
new Animal()
{
public void eat() {
System.out.println("I can eat from an anonymous class");
}
public void move() {
System.out.println("I can move from an anonymous class");
}
});
}
}
public class Cat implements Animal
{
public void eat() {
System.out.println("Cat: I can eat");
}
public void move(){
System.out.println("Cat: I can move");
}
}
public class Dog implements Animal
{
public void eat() {
System.out.println("Dog: I can eat");
}
public void move() {
System.out.println("Dog: I can move");
}
}
public class Human {
int height;
int weight;
public void eat() {
System.out.println("I can eat!");
}
}
public class Man extends Human {
public void eat() {
System.out.println("I can eat more");
}
public void plough() {
}
public static void main(String[] a) {
Man obj1 = new Man();
obj1.eat(); // call Man.eat()
Human obj2 = (Human) obj1;
obj2.eat(); // call Man.eat()
Man obj3 = (Man) obj2;
obj3.eat(); // call Man.eat()
}
}