java继承与接口详解
继承
概念:
继承就是子类继承父类,是类与类之间的继承。类与类之间的差距还是很大的,比如说学生类,可以细分为大学生类、研究生类、高中生类等。他们之间既有相同属性,比如说学号、年龄、姓名等,又有不同的属性,比如说高中没有学院、专业的概念等。
继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。
用法:
先给个需求吧,比如说用于描述动物,假设动物有名称、移动方式、重量这三个属性,我们可以创建一个Animal类,并创建成员变量。
public class Animal {
//成员变量
public String AnimalName;//动物名称
public String WayOfMove;//动物移动方式
public String Weight;//动物重量
}
然后再给他一些行为,比如说,动物需要进食、运动、睡觉等,
//吃饭行为
public void animalEat() {
System.out.println(AnimalName+"正在吃饭");
}
//运动行为
public void animalSport() {
System.out.println(AnimalName+"正在用"+WayOfMove+"的方式运动,她已经有"+Weight+"公斤重了");
}
//睡觉行为行为
public void animalSleep() {
System.out.println(AnimalName+"正在睡觉");
}
以上是对动物的一个大概的描述,现在我养了一只狗和一条鱼,我想用上面的Animal类去描述我的狗和鱼,这时候需要用到继承的概念,狗类和鱼类都属于动物类。是他的子集,以后如果我要描述其他的动物都可以通过继承的方式去描述,代码更加简洁。
继承用到了extends关键字
public class Dog extends Animal {
public static void main(String[] args) {
Dog aHuang = new Dog();
aHuang.AnimalName = "阿黄";
aHuang.WayOfMove = "奔跑";
aHuang.Weight = 25.5F;
aHuang.animalEat();
aHuang.animalSport();
aHuang.animalSleep();
}
}
Dog类继承Animal类会获得Animal类的所有属性,运行结果应该为:
阿黄正在吃饭
阿黄正在用奔跑的方式运动,她已经有25.5公斤重了
阿黄正在睡觉
但是上面的代码子类直接给父类的成员变量赋值,可能会出现安全性问题,这里要用getset方法
get方法和set方法
顾名思义,这两个方法,一个得到成员变量的值,一个设置成员变量的值,他们提供了一个中间变量去做这个任务,提高了数据的安全性,并且我们可以供private去修饰成员变量,禁止子类直接访问父类的成员变量。
public class Animal {
//成员变量
private String AnimalName;//动物名称
private String WayOfMove;//动物移动方式
private float Weight;//动物重量
//getset方法
public String getAnimalName() {
return AnimalName;
}
public String getWayOfMove() {
return WayOfMove;
}
public float getWeight() {
return Weight;
}
public void setAnimalName(String animalName) {
AnimalName = animalName;
}
public void setWayOfMove(String wayOfMove) {
WayOfMove = wayOfMove;
}
public void setWeight(float weight) {
Weight = weight;
}
}
测试类修改为:
public class Dog extends Animal {
public static void main(String[] args) {
Dog aHuang = new Dog();
aHuang.setAnimalName("阿黄");
aHuang.setWayOfMove("奔跑");
aHuang.setWeight(25.5F);
aHuang.animalEat();
aHuang.animalSport();
aHuang.animalSleep();
}
}
可以提高数据安全性。
现在需要用Animal去描述鱼类了。但是我养的这个鱼是用来吃的,我觉得他应该有 吃法 这个属性,比如说鲈鱼适合清蒸,鲤鱼适合红烧等,但是Animal类并没有这个属性,而且我也不需要Animal类中的WayOfMove这个成员变量,我们依旧可以使用继承,
子类继承父类后,获得父类的所有属性,并可以在父类基础上进行扩展
我们创建鱼这个类
public class Fish extends Animal {
//定义新的成员变量
private String WayOfEat;
public String getWayOfEat() {
return WayOfEat;
}
public void setWayOfEat(String wayOfEat) {
WayOfEat = wayOfEat;
}
//新的成员方法,吃鱼
public void eatWay() {
System.out.println(getAnimalName()+WayOfEat+"最好吃");
}
public static void main(String[] args) {
Fish fish = new Fish();
fish.WayOfEat = "清蒸";
fish.setAnimalName("鲈鱼");
fish.eatWay();
}
}
可以看到,我们增加了新的成员变量 WayOfEat和新的成员方法eatWay()
注:上面代码中的get和set方法使用IDEA的话,可以使用快捷键 alt+insert来快速生成代码,提高效率。
这个时候我们在想,能不能继续优化代码,Animal类能不能把他做的更抽象,动物本来就是个抽象的概念。上面的代码Animal类中给出了具体的实现方法,但是我们在使用的过程中可以发现,不同的动物有不同的行为,就是不同的类会执行不同的方法,如果按照上面的代码,我们总是得修改具体实现过程才能完美匹配当前的类的行为,这明显增加了工作量,并且增加了代码量。
那么能不能我只写个方法名,不写具体实现过程,把动物的行为都定义出来,但是具体哪一种动物是怎么做的不管,由子类去具体实现,这样可以增加代码的可读性,这里引出了接口的概念。
接口
概念
接口是一组规则的集合,它规定了实现本接口的类或接口必须拥有的一组规则。体现了自然界“如果你是……则必须能……”的理念。
用法
java类是以.class为文件后缀的,而接口是以.interface作为文件后缀的,接口中只有抽象方法和抽象类,
值得注意的是,根据阿里的java命名规范:
**【强制】抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾;测试类
命名以它要测试的类的名称开始,以 Test 结尾**
【推荐】接口类中的方法和属性不要加任何修饰符号(public 也不要加),保持代码的简洁
性,并加上有效的 Javadoc 注释。尽量不要在接口里定义变量,如果一定要定义变量,肯定是
与接口方法相关,并且是整个应用的基础常量。
正例:接口方法签名:void f();
接口基础常量表示:String COMPANY = “alibaba”;
反例:接口方法定义:public abstract void f();
说明:JDK8 中接口允许有默认实现,那么这个 default 方法,是对所有实现类都有价值的默
认实现。
Animals接口
public interface Animals {
//定义抽象方法
//动物吃饭方法
void animalEat();
//动物睡觉
void animalSleep();
//动物运动
void animalSport();
//动物吃法
void animalWayOfEat();
}
AbstractAnimal抽象类
package Review;
public class AbstractAnimal implements Animals {
//成员变量
private String AnimalName;//动物名称
private String WayOfMove;//动物移动方式
private float Weight;//动物重量
//getset方法
public String getAnimalName() {
return AnimalName;
}
public String getWayOfMove() {
return WayOfMove;
}
public float getWeight() {
return Weight;
}
public void setAnimalName(String animalName) {
AnimalName = animalName;
}
public void setWayOfMove(String wayOfMove) {
WayOfMove = wayOfMove;
}
public void setWeight(float weight) {
Weight = weight;
}
@Override
public void animalEat() {
}
@Override
public void animalSleep() {
}
@Override
public void animalSport() {
}
@Override
public void animalWayOfEat() {
}
}
NewDog类
package Review;
public class NewDog extends AbstractAnimal {
public static void main(String[] args) {
NewDog aHuang = new NewDog();
aHuang.setAnimalName("阿黄");
aHuang.setWayOfMove("奔跑");
aHuang.setWeight(25.5F);
aHuang.animalEat();
aHuang.animalSport();
aHuang.animalSleep();
}
}
NewFish类
package Review;
public class NewFish extends AbstractAnimal{
//定义新的成员变量
private String WayOfEat;
public String getWayOfEat() {
return WayOfEat;
}
public void setWayOfEat(String wayOfEat) {
WayOfEat = wayOfEat;
}
public void WayOfEat() {
System.out.println(getAnimalName()+WayOfEat+"最好吃");
}
public static void main(String[] args) {
Fish fish = new Fish();
fish.setWayOfEat("清蒸");
fish.setAnimalName("鲈鱼");
fish.eatWay();
}
}