继承
生活中的继承 :爷爷–爸爸–儿子–孙子
Java中的继承更像包含关系:娱乐圈艺人–演员–优秀的演员
我们称为子类继承 父类,也可以接口继承接口。
继承必要时能大大简便我们的代码量。
类分为具体的类和抽象的类(关键字:abstract )。具体的类不依赖抽象的类,而抽象的类依赖具体的类之后使得扩展更方便。举例如下:
//抽象类
public abstract class Actor {
//定义一个成员变量
String name;
//定义一个常量
final String job="演员";
//普通方法可以具体也可以抽象
public void Perform() {
}
//抽象方法只允许声明,不允许实现
abstract public void act();
//接口
public interface Can_do {
public void Sing() ;
public void Dance();
}
//继承父类并实现接口
public class Idol extends Actor implements Can_do{
//主函数
public static void main(String[] args) {
Idol my_idol=new Idol();
//当前类并没有定义变量name却能直接调用,是因为继承了Actor类
my_idol.name="李现";
System.out.println(my_idol.name+"的职业是"+my_idol.job);
my_idol.Perform();
my_idol.Sing();
my_idol.Dance();
my_idol.act();
}
//实现接口必须重写接口中的所有方法
public void Sing() {
System.out.println(name+"会唱歌");
}
public void Dance() {
System.out.println(name+"会跳舞");
}
//对父类的普通方法进行重写,除方法体之外,其他需与父类一致
public void Perform() {
System.out.println(name+"会表演");
}
//对父类的抽象方法进行重写时需要去掉abstract
public void act(){
System.out.println(name+"会act");
}
}
程序运行结果为:
李现的职业是演员
李现会表演
李现会唱歌
李现会跳舞
李现会act
抽象类和接口的区别与联系
抽象类(侧重于本质) | 接口(侧重于功能) |
---|---|
有构造方法 | 没有构造方法 |
里面可以有变量和常量 | 只能是常量 |
方法可抽象可具体 | 方法默认抽象 |
类和类:之间可以实现单继承和多层继承
类和接口:是实现关系,类可以在继承类的同时实现多个接口
接口与接口:单继承和多继承
继承的访问权限
如果是缺省,那么同包下都可以访问。
default:上表中的子类不能访问是指不同包中的子类,在同一个包内继承的子类是可以访问default修饰的属性和方法的!什么都不写时默认default。
protect:可以被不同包中的子类访问。也就是说,对于父类自己声明的protected的属性和方法,只要子类和父类在一个包中即可,如果父类中的protected修饰的属性和方法也是继承来的,那么我们需要追溯到祖宗类,如果该类和祖宗类在一个包中,也可以进行访问。
我们来思考这样一个问题:如果不同的子类继承了父类的方法,但是它们的又想扩展自己的属性和方法,那怎么办呢?方法重写。
方法重写
当父类中的方法不足以满足子类的需求时,我们可以对方法进行重写。并且优先调用子类的方法。格式要求: 除方法体之外(访问权限修饰符 返回值类型 方法名(参数类型 参数变量名))必须与父类一致。
//父类
public class Father {
public void ways() {
System.out.println("这是父类中的方法");
}
}
//子类
public class Son extends Father {
//主函数
public static void main (String[] args) {
Son son=new Son();
son.ways();
}
//对父类中的方法进行重写
public void ways() {
System.out.println("这是子类中的方法");
}
}
运行结果为:
这是子类中的方法
通过方法重写,使得一个方法在被调用时产生了不同的行为,也就是多态。
转型
自动转型:
我们在创建对象时(类名 变量名=new 类名( );)经历了这几个步骤:
1:创建了一个对象;
2:声明了一个某类型的变量名;
3:返回对象所在的引用地址给变量名;
而子类可以向父类转化,即小范围转化为大范围,是因为一个子类对象所保存的引用地址也可以保存在父类类型的变量名中。
格式:父类名 变量名=new 子类名();
那通过转型创建的子类对象和直接创建的子类对象有什么区别呢?
相同点:当子类对方法进行重写时,调用的都是重写之后的方法。
不同点:直接创建的子类对象可以调用子类独有的方法,而转型之后的子类不能调用子类有但是父类没有的方法。举例如下:
package 继承与封装0919;
//父类
public class Father {
public void ways() {
System.out.println("这是父类中的方法");
}
}
package 继承与封装0919;
//子类继承父类
public class Son extends Father {
//主函数
public static void main (String[] args) {
Son son=new Son();
//自动转型
Father son2=new Son();
//打印输出两者的地址
System.out.println(son.getClass());
System.out.println(son2.getClass());
son2.ways();
//son2.son_ways();子类有而父类没有的方法是不能调用的
}
public void ways() {
System.out.println("这是子类中的方法");
}
public void son_ways() {
System.out.println("这是子类独有的方法");
}
}
程序运行结果为:
class 继承与封装0919.Son
class 继承与封装0919.Son
这是子类中的方法
封装
用private私有化成员属性,同时又提供public的setter(取值)和getter(赋值),以保证信息的私密性和安全性,还可以进行信息检测,对异常进行处理。
访问修饰符:private
public class Father {
private String name;
private int age;
public void setname(String name) {
//判断用户名输入是否合法
if(name!=null||name!="") {
this.name=name;
System.out.println("用户名为:"+name);
}else {
System.err.println("用户名输入非法");
}
}
public void setage(int age) {
//判断年龄输入是否合法
if(age>=0) {
this.age=age;
}else {
System.err.println("年龄输入非法");
}
}
//获得方法
public int getage() {
return this.age;
}
}
public class Son{
public static void main(String[] args) {
Father son=new Father();
son.setname("小明");
son.setage(18);
//获取age值
int age=son.getage();
System.out.println("用户年龄为:"+age);
}
}
程序运行结果为:
用户名为:小明
用户年龄为:18
封装说白了就是不让外界太轻易的访问到私密信息,需要经过稍微复杂一点地位操作以达到保密的目的。