面向对象的三大特征:封装、继承、多态
封装和继承,在Java面向对象的详解一中http://t.csdn.cn/pavlZ
目录
一、多态
1、概念:
同类型的对象,表现的不同的形态
比如:同一件事情,吃,对狗来说是吃狗粮,对猫咪来说是吃猫粮,而他们都是属于动物类
2、多态的表现形式
父类类型 对象名称 = 子类对象
3、多态的前提
1、有继承关系
2、有父类引用指向子类对象
3、有方法重写
上代码感受一下:
class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void Show() {
System.out.println(name+age);
}
}
class Student extends Person {
public void Show() {
System.out.println("学生的信息为:"+getName()+" "+getAge());
}
}
class Teacher extends Person {
public void Show() {
System.out.println("老师的信息为:"+getName()+" "+getAge());
}
}
class Counselor extends Person {
public void Show() {
System.out.println("辅导员的信息为:"+getName()+" "+getAge());
}
}
public class Poly {
public static void register(Person p) {
p.Show();
}
public static void main(String[] args) {
//创建3个对象,调用register方法
Student s = new Student();
s.setName("静静");
s.setAge(18);
Teacher t = new Teacher();
t.setName("洋洋");
t.setAge(60);
Counselor c=new Counselor();//导员
c.setName("小张");
c.setAge(28);
register(s);
register(t);
register(c);
}
}
Person这个父类下,有三个子类,分别创建了三个对象,调用同一个函数register,他们三个是不同的类型,按理来说,传参时,这个函数,用什么来接收,是一个问题。
因此,在这里就体现了多态,用他们的父类Perosn来作为接收的形参类型,当调用函数Show时,还可以根据原本的相应类型的子类,来调用对象的类中的Show函数.
输出结果:
总结:
4、多态的好处
- 使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利
- 在多态形式下,右边的对象可以实现解耦合,便于扩展和维护
5、多态调用成员的特点
- 变量调用:编译看左边,运行看左边
- 方法调用:编译看左边,运行看右边
上代码理解;
先看创建的父子类:
class Animal {
String name ="动物";
public void Show() {
System.out.println("Animal----Show");
}
}
class Dog extends Animal {
String name ="狗";
public void Show() {
System.out.println("Dog-----Show");
}
}
class Cat extends Animal {
String name ="猫";
public void Show() {
System.out.println("Cat-----Show");
}
}
创建对象:
public class Poly {
public static void main(String[] args) {
//创建对象
Animal a=new Dog();
System.out.println(a.name);
}
}
思考输出结果为动物还是狗
正确结果:
为什么呢?这就是多态调用成员属性的特点: 编译看左边,运行看左边
具体:
编译看左边,我们将Animal类中String name="动物";这行代码删除,我们会发现,还没有运行,直接报错,这就是Java中编译错误。
运行看左边,Java运行代码时,实际获取的是左边中的成员变量的值
看下列代码:
public class Poly {
public static void main(String[] args) {
//创建对象
Animal a=new Dog();
a.Show();
}
}
思考,会输出什么呢?
正确输出:
原因:方法调用:编译看左边,运行看右边
总结:
- 成员变量:在子类的对象中,会把父类的成员变量也继承下来(如上例中,会有2个name,具体就是运行看左边了)。
- 成员方法:如果子类对方法进行了重写,那么在虚方法表中会把父类的方法覆盖
6、多态的弊端
继续看这个代码:
public class Poly {
public static void main(String[] args) {
//创建对象
Animal a=new Dog();
a.Show();
}
}
因为在调用方法及变量时,编译看左边,如果父类中,没有Show方法或者相应的变量,那这个调用就会报编译性错误
解决方案:类似于强制类型转换
(下列代码的父子类与上面的一样,只是把父类中的Show方法删掉了)
public class Poly {
public static void main(String[] args) {
//创建对象
Animal a=new Dog();
Dog d=(Dog)a;
d.Show();
}
}
注意不要乱转类型。
总结:多态的弊端:不能使用子类中的特有的功能
二、包
1、什么是包
包就是文件夹,管理各种不同功能的Java类,方便后期维护
包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一 个包中的类不想被其他包中的类使用。包还有一个重要的作用:在同一个工程中允许存在相 同名称 的类,只要处在 不同的包中即可
2、导入包中的类
规则:
- 使用同一个包中的类时,已近导过了,就不用再导包了
- 使用Java.lang包中的类,不需要导包
- 如果同时使用两个包中的同类名,需要用全类名
更建议显式的指定要导入的类名. 否则还是容易出现冲突
什么是全类名?
包名+类名
3、自定义包
(1、规则:
(2、IDEA中自定义包的操作步骤:
步骤一:右键src
步骤二:
步骤三:
然后回车就好啦
三、关键字——final
final可以修饰方法、类、变量
修饰方法:表明该方法是最终方法,不能被重写
修饰类:表明该类是最终类,不能被继承
修饰变量:叫做常量,只能被赋值一次
注意:
- final修饰基本类型的变量:变量存储的数据值不能发生改变
- final修饰引用类型的变量:变量存储的地址值不能发生改变,对象内部的可以改变
四、权限修饰符
Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起
- 权限修饰符:是用来控制一个成员能够被访问的范围的
- 可以修饰成员变量、方法、构造方法、内部类
权限修饰符的分类
4种作用范围由小到大(private<空着不写<protected<public)
一般只用private和public
在类中,一般遵守:
- 成员变量私有
- 方法公开
好啦,本期结束了,后续持续更新呀!!!