封装、继承和多态。
访问修饰符 | 范围 |
---|---|
private | 类内 |
default | 包内 |
protected | 包内,非同包子类 |
public | 公共的 |
封装
封装是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问到对象内部信息,通过该类中的方法对内部信息进行操作和访问。
2.
继承
继承是在原有类的基础上创建一个新类,用extends实现,从而达到代码复用的目的。
方法覆盖:当父类方法不能满足子类需要时,子类可以重写父类方法
1.方法重写:
子类扩展完父类,为满足自身需要,对父类行为或方法进行覆盖,换句话说就是子类包含与父类同名方法的现象
/*
什么时候我们会考虑使用方法覆盖呢?
子类继承父类之后,当继承过来的方法无法满足当前子类的业务需求时,
子类有权利对这个方法进行重新编写,有必要进行"方法的覆盖"
重要结论:
当子类对父类继承过来的方法进行"方法覆盖"之后,
子类对象调用该方法的时候,一定执行覆盖之后的方法
方法重写只存在于继承关系中;
方法重写时子类、父类的方法名相同,参数列表也相同(同名同参);
子类方法的返回值类型与父类相同(return),或者子类返回值类型是父类返回值类型的子类(public Son Study(){});
子类方法抛出异常<父类方法抛出异常;(父类子类没有异常,父类抛出异常,程序正常运行父类子类没有异常,子类抛出异常,程序报错:)
子类方法的访问权限>=父类方法的访问权限;(**父类方法private除外子类不能访问,更无法重写**)(父类原先是public,不能低于public。父类原先是protected,子类可以是public)
(**满足以上五点不一定是方法重写**,如子类和父类刚好有相同方法或者private修饰父类方法,即使子类写的相同也相当于写了一个新方法,但是如果子类的方法名、参数、访问权限、异常都相同,只有返回值类型不同编译会不通过)
注意1:方法覆盖只是针对于方法,和属性无关
注意2:私有方法无法覆盖
注意3:构造方法不能被继承,所以构造方法也不能被覆盖.
注意4:方法覆盖只是针对于实例方法,静态方法覆盖没有意义.
*/
//方法覆盖比较经典的案例
//一定要注意:方法覆盖/重写的时候,建议将父类的方法复制粘贴,这样比较保险
class People{
//属性
private String name;
//构造
public People(){}
public People(String name){
this.name = name;
}
//setter and getter
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
//人都会说话
public void speak(){
System.out.println(name + "....");
}
}
//中国人
class Chinese extends People{
//中国人说汉语
//所以子类需要对父类的speak()方法进行重写
public void speak(){
System.out.println(this.getName() + "正在说汉语");
}
}
//美国人
class American extends People{
//美国人说英语
//所以子类需要对父类的speak()方法进行重写
public void speak(){
System.out.println(this.getName() + "speak english!");
}
}
public class OverrideTest03{
public static void main(String[] args){
//创建中国人对象
// Chinese p1 = new Chinese("张三");//错误原因:没有这样的构造方法
Chinese p1 = new Chinese();
p1.setName("张三");
p1.speak();//张三正在说汉语
//创建美国人对象
// American p2 = new American("jack");//错误原因:没有这样的构造方法
American p2 = new American();
p2.setName("jack");
p2.speak();//jack speak english!
}
}
2.方法重载(类方法也行)
定义(3点):同类中、方法名相同、参数列表不同(个数、类型)
特征(三无关一有关):访问修饰符(可以不同)、方法返回值(不同也可以)、抛出异常无关,参数列表有关
/*
什么时候考虑使用方法重载overload?
当在一个类当中,如果功能相似的话,建议将名字定义的一样,这样代码美 观,并且方便编程
什么条件满足之后能够构成方法重载overload?
条件一:在同一个类当中
条件二:方法名相同
条件三:参数列表不同(个数、顺序、类型)
*/
public class MethodDemo03 {
public static void main(String[] args) {
// 下面是针对求和方法的调用
int sum1 = add(1, 2);
int sum2 = add(1, 2, 3);
double sum3 = add(1.2, 2.3);
// 下面的代码是打印求和的结果
System.out.println("sum1=" + sum1);
System.out.println("sum2=" + sum2);
System.out.println("sum3=" + sum3);
}
// 下面的方法实现了两个整数相加
public static int add(int x, int y) {
return x + y;
}
// 下面的方法实现了三个整数相加
public static int add(int x, int y, int z) {
return x + y + z;
}
// 下面的方法实现了两个小数相加
public static double add(double x, double y) {
return x + y;
}
}
多态
多态是对象的相同的数据类型,使用同一种方法时呈现出的不同状态特征,当
[编译时类型] 是由声明该变量时使用的类型所决定
不等于
[运行时类型] 是由该变量指向的对象类型决定
时,会产生多态。
简单的来说就是父类引用指向子类对象或者是接口引用指向实现类对象 在调用方法和属性的时候 实际上调用的就是子类的方法和父类的属性 子类对方法的重写会覆盖父类的定义 但是对属性的重新定义不会覆盖父类的定义
会将子类对象直接赋值给父类引用变量,称为向上转型,而不用进行类型转换。如 Animal a = new Bird()
,其中引用变量 a 的编译时类型是 Animal,运行时类型是 Bird,两者不一致,因此出现多态。
当使用该对象引用进行调用的时候,有这么一条规则,对象调用编译时类型的属性和运行时类型的方法
/*1.多态的前提:继承+重写*/
//1.创建父类
class Animal{
//3.创建父类的普通方法
public void eat(){
System.out.println("小动物Animal吃啥都行~");
}
}
//2.1创建子类1
class Cat extends Animal{
//4.1添加重写的方法
@Override
public void eat(){
System.out.println("小猫爱吃小鱼干~");
}
//5.1添加子类的特有功能
public void jump(){
System.out.println("小猫Cat跳的老高啦~");
}
}
//2.2创建子类2
class Dog extends Animal{
//4.2添加重写的方法
@Override
public void eat(){
System.out.println("小狗爱吃肉骨头~");
}
//5.2添加子类的特有功能
public void run(){
System.out.println("小狗Dog跑的老快啦~");
}
}
public class TestDemo {
public static void main(String[] args) {
//6.创建“纯纯的”对象用于测试
Animal a = new Animal();
Cat c = new Cat();
Dog d = new Dog();
a.eat();//小动物Animal吃啥都行~调用的是父类自己的功能
c.eat();//小猫爱吃小鱼干~调用的是子类重写后的功能
d.eat();//小狗爱吃肉骨头~调用的是子类重写后的功能
/*2.父类对象不可以使用子类的特有功能*/
//a.jump();//报错,Animal类里并没有这个方法
//a.run();//报错,Animal类里并没有这个方法
c.jump();//小猫Cat跳的老高啦~,子类可以调用自己的功能
d.run();//小狗Dog跑的老快啦~,子类可以调用自己的功能
//7.创建多态对象进行测试
/*3.口诀1:父类引用指向子类对象
* 解释:创建出来的子类对象的地址值,交给父类类型的引用类型变量来保存*/
Animal a2 = new Cat();//Cat类对象的地址值交给父类型变量a2来保存
Animal a3 = new Dog();//Dog类对象的地址值交给父类型变量a3来保存
//8.测试多态对象
/*4.口诀2:编译看左边,运行看右边
* 解释:必须要在父类定义这个方法,才能通过编译,把多态对象看作是父类类型
* 必须要在子类重写这个方法,才能满足多态,实际干活的是子类*/
a2.eat();//小猫爱吃小鱼干~,多态对象使用的是父类的定义,子类的方法体
}
}
采用面向对象的方法开发一个软件,生命周期当中:【整个生命周期中贯穿使用面向对象方式】
面向对象的分析:OOA
面向对象的设计:OOD
面向对象的编程:OOP
程序员的抽象能力-->将现实世界转换为代码