系列文章目录
前言
面向对象编程有三大特征: 封装、 继承和多态。
一、封装
封装(encapsulation)就是把抽象出的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作【方法】,才能对数据进行操作。
封装的好处 隐藏实现细节:方法(链接数据库)<–调用(传入参数) 可以对数据进行验证,保证安全合理
实现封装的三个步骤 属性私有化private 提供一个公共的(public)set方法,用于对属性判断并赋值 提供一个公共的(public)get方法,用于获取属性的值
二、继承
继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法, 所有的子类不需要重新定义这些属性和方法, 只需要通过 extends 来声明继承父类即可。
class 子类 extends 父类
{ }
继承的好处 代码的复用性提高了 代码的扩展性和维护性提高了
继承的使用细则 子类会自动拥有父类定义的属性和方法 子类又叫派生类,父类又叫超类、基类 子类必须调用父类的构造器, 完成父类的初始化 不能滥用继承, 子类和父类之间必须满足 is-a 的逻辑关系 java 所有类都是 Object 类的子类, Object 是所有类的基类 父类构造器的调用不限于直接父类! 将一直往上追溯直到 Object 类(顶级父类) 子类最多只能继承一个父类(指直接继承), 即 java 中是单继承机制 super 在使用时, 必须放在构造器第一行(super 只能在构造器中使用) super() 和 this() 都只能放在构造器第一行, 因此这两个方法不能共存在一个构造器 如果希望指定去调用父类的某个构造器, 则显式的调用一下 : super(参数列表) 子类继承了所有的属性和方法, 非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问, 要通过父类提供公共的方法去访问 当创建子类对象时, 不管使用子类的哪个构造器, 默认情况下总会去调用父类的无参构造器, 如果父类没有提供无参构造器, 则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作, 否则, 编译不会通过
继承的本质 先加载父类信息和父类属性 首先看本类是否有该属性或方法,如果本类没有就看父类有没有,直到Object 找到了但不能访问或找不到就报错,如此反复循环寻找
package com. hspedu. extend_ ;
public class ExtendsTheory {
public static void main ( String [ ] args) {
Son son = new Son ( ) ;
System . out. println ( son. name) ;
System . out. println ( son. hobby) ;
}
}
class GrandPa {
String name = "大头爷爷" ;
String hobby = "旅游" ;
}
class Father extends GrandPa {
String name = "大头爸爸" ;
private int age = 39 ;
public int getAge ( ) {
return age;
}
}
class Son extends Father {
String name = "大头儿子" ;
}
三、多态
方法或对象具有多种形态,多态是建立在封装和继承基础之上的,多态的前提的是:两个对象(类)存在继承关系。
多态的应用 方法的多态:方法的重载 对象的多态:编译类型与运行类型(也称为方法的覆盖/重写) 属性没有多态:属性的值看编译类型
编译类型与运行类型 编译类型为对象引用的类型,运行类型为对象本身的类型 编译类型看定义时 = 号的左边,运行类型看 = 号的右边 一个对象的编译类型和运行类型可以不一致 编译类型是不能改变的(javac) 运行类型是可以改变的(java)
向上转型 本质父类的引用指向子类对象 父类类型 引用名 = new 子类类型(); 可以调用父类中的所有成员(需要遵守访问权限) 不能调用子类中特有成员 最终运行效果看子类的具体实现
向下转型 本质子类的引用指向子类对象 子类类型 引用名 = (子类类型)父类引用 只能强转父类的引用,不能强转父类对象 要求父类引用必须指向当前目标类型的对象 可以调用子类类型中所有成员(需要遵守访问权限)
instanceof 比较操作符 bb instanceof BB 用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型
动态绑定机制 当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
package com. hspedu. poly_. dynamic_ ;
public class DynamicBinding {
public static void main ( String [ ] args) {
A a = new B ( ) ;
System . out. println ( a. sum ( ) ) ;
System . out. println ( a. sum1 ( ) ) ;
}
}
class A {
public int i = 10 ;
public int sum ( ) {
return getI ( ) + 10 ;
}
public int sum1 ( ) {
return i + 10 ;
}
public int getI ( ) {
return i;
}
}
class B extends A {
public int i = 20 ;
public int getI ( ) {
return i;
}
}
多态的应用 多态数组:用数组指向向上转型的对象,数组存储的是父类型编译类型的对象名 多态参数:方法定义的形参类型为父类型,实参类型允许为子类类型
package com. hspedu. poly_. polyarr_ ;
public class PloyArray {
public static void main ( String [ ] args) {
Person [ ] persons = new Person [ 5 ] ;
persons[ 0 ] = new Person ( "jack" , 20 ) ;
persons[ 1 ] = new Student ( "mary" , 18 , 100 ) ;
persons[ 2 ] = new Student ( "smith" , 19 , 30.1 ) ;
persons[ 3 ] = new Teacher ( "scott" , 30 , 20000 ) ;
persons[ 4 ] = new Teacher ( "king" , 50 , 25000 ) ;
for ( int i = 0 ; i < persons. length; i++ ) {
System . out. println ( persons[ i] . say ( ) ) ;
if ( persons[ i] instanceof Student ) {
Student student = ( Student ) persons[ i] ;
student. study ( ) ;
} else if ( persons[ i] instanceof Teacher ) {
Teacher teacher = ( Teacher ) persons[ i] ;
teacher. teach ( ) ;
} else if ( persons[ i] instanceof Person ) {
} else {
System . out. println ( "你的类型有误, 请自己检查..." ) ;
}
}
}
}
package com. hspedu. poly_. polyparameter_ ;
public class PloyParameter {
public static void main ( String [ ] args) {
Worker tom = new Worker ( "tom" , 2500 ) ;
Manager milan = new Manager ( "milan" , 5000 , 200000 ) ;
PloyParameter ployParameter = new PloyParameter ( ) ;
ployParameter. showEmpAnnual ( tom) ;
ployParameter. showEmpAnnual ( milan) ;
ployParameter. testWork ( tom) ;
ployParameter. testWork ( milan) ;
}
public void showEmpAnnual ( Employee e) {
System . out. println ( e. getAnnual ( ) ) ;
}
public void testWork ( Employee e) {
if ( e instanceof Worker ) {
( ( Worker ) e) . work ( ) ;
} else if ( e instanceof Manager ) {
( ( Manager ) e) . manage ( ) ;
} else {
System . out. println ( "不做处理..." ) ;
}
}
}
总结
封装、 继承和多态每一个特征都很重要。