一、封装
一般封装是针对类的属性封装,我们先看看不使用封装的结果
//定义一个student类
public class Student {
public int age;
}
//定义一个client类调用他
public class Client {
public static void main(String[] args) {
Student student = new Student();
//呀!类的属性就这么随意的被改了,改了就算了,还被赋值成-1,人的年纪怎么可能是-1
student.age = -1;
System.out.println("student的年纪是:"+student.age);
}
}
从上面看,student的年纪这么随便就被改了,而且还被赋值成了-1,年纪是-1这显然是不合理的,所以解决方式如下
1、将属性设置为private,不许类的外部随便改动
2、要改动属性,必须走我提供的一个入口,获取属性也是
3、对类的值赋值作规则限制,过滤不合法的值
那现在我们把代码改造一下
public class Student {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age>=0 && age<120){
this.age = age;
}
else {
System.out.println("输入的数字不合法");
}
}
}
public class Client {
public static void main(String[] args) {
Student student = new Student();
//不合法数字
student.setAge(-1);
//合法数字
student.setAge(50);
System.out.println(student.getAge());
}
}
输出结果:
输入的数字不合法
50
封装的实现如下
1、需要修改属性的访问控制符为private;
2、创建getter/setter方法用于属性的读写;
3、在getter/setter方法中加入属性控制语句,用于判断属性值的合法性;
优点: 数据更安全 缺点:不能直接访问,增加了访问难度
二、继承 (extends)
1、首先我们看一下继承的规则
(1)首先我们定义一个父类
(2)再定义一个子类,重写父类 Person中的一个静态方法
在静态方法重写时,他报错了
(3) 再作一个实验
public class Person {
public void run() {
System.out.println("father run");
}
}
public class Student extends Person {
@Override
public void run() {
System.out.println("sun run");
}
}
子类重写复类的普通方法,没有报错
2、再看看重写以后的调用
//父类
public class Person {
public static String name = "father";
public int age =15;
private String sex = "女";
public String action ="father run";
public void run() {
System.out.println("father run");
}
}
//子类
public class Student extends Person {
public String action = "son run";
@Override
public void run() {
System.out.println(this.action);
System.out.println(super.action);
super.run();
}
}
//调用
public class Client {
public static void main(String[] args) {
Student student = new Student();
System.out.println(Student.name); // 静态属性和静态方法可以调用,不过要用子类的类名调用
System.out.println(student.age); // 直接用对像调用
System.out.println(student.sex); // 报错。父类的私有方法和属性不可以调用
System.out.println(student.action); // 属性或方法重新后,调用子类中的属性或方法,输出sun run
student.run();
// 因为子类重写父类中的run方法,所以调用子类中的run方法
// this 代表输出本类中的信息,因此this.action输出 "son run“
// super 代表输出父类中的信息,因此super.action输出 "father run"
// super.run 代表输入父类中的run方法 ,因此输出 "father run"
}
}
总结:
一、继承:
1、子类要比父类强大
2、父类相当于子类的模板,可以将共公部分定义成父类,减少代码量
3、继承是实现多态的前题
4、父类中的私有函数和方法不能继承
5、父类的静态主方法不可以被子类重写
6、用子类的类名可以调用父类的静态属性或静态方法
缺点:父类的方法和属性发生变化,子类也会发生变化,造成类与类之前的强偶合
二、继承中的方法重写
1、方法名必须相同
2、参数列表必须相同
3、函数的修饰符可以扩大,但不可以缩小
4、抛出的异常范围可以缩小 。但不可以扩大
三、super和this
1、super:
子类中调用父类的构造方法是,必须写在子类构造方法的第一行,否则会报氏
super只能用在子类的构造方法和方法中
2、super和this的区别
(1)this 代表本身对像 ,super代表父类
(2)this 没有继承也可以使用,super必须有继承才能使用
(3)this()代表本类的构造 , super() 代表父类的构造
三、多态
public class Person {
public void run() {
System.out.println("son run ");
}
public void eat(){
System.out.println("father eat"); //父类独有的方法
}
}
public class Student extends Person {
@Override
public void run() {
System.out.println("son run "); //重写父类方法
}
public void jump(){
System.out.println("son jump"); //子类独有方法
}
}
public class Client {
public static void main(String[] args) {
Student student = new Student();
Person person = new Student();
student.run(); //父类的方法被重写,调用子类的run
person.run(); //父类的方法被重写,调用子类的run
student.eat(); //继承父类的eat,调用父类的eat
person.eat(); // 调用父类中的eat
student.jump(); //子类自己的方法,子类可以调用
person.jump(); //会报错,=不可以调用子类自己的方法
((Student) person).jump();//如果在调用,需要将person转为student类型
}
多态:
创建父类多像指向子类
Student student = new Student();
Person person = new Student();1、如果是父类方法,子类对像和父类对像都可以调用
2、如果子类重写了父类的方法,子类对像和父类对像调用的都是子类的重写方法
3、如果是子类的方法,父类对像中果调用需要转型为子类
即对像能执行哪些方法,主要看对像左边的类型,和右边关系不大
特点
多态指的是对象的多种形态。继承是多态的实现基础。