面向对象(下)***
继承
概念:
类的继承是指在现有类的基础上去构建一个新的类,构建出来的新类被称作子类,现有类被称作父类或基类,子类会自动拥有父类所有可继承的属性和方法。
语法格式:
[ 修饰符] class 子类名 extends 父类名{
}
注意:
类的修饰符是可选的, 用来指定类的访问权限, 可以使用public 或者省略不写
子类名和父类名都是必选的, 并且子类与父类之间要用extends 关键字实现继承关系
案例代码
public class Test2 {
public static void main ( String [ ] args) {
Dog d= new Dog ( ) ;
d. eat ( ) ;
}
}
class Animal {
public void eat ( ) {
System . out. println ( "Animal eat" ) ;
}
}
class Dog extends Animal {
}
继承的注意事项
优点:
1. 提高代码的复用性
2. 提高了代码的维护性
3. 类和类之间产生联系( 多态前提)
缺点:
1. 侵入性
2. 降低了代码的灵活性
3. 增强了代码的耦合性
应用场景:
类和类之间存在共性的内容, 可以考虑使用继承来优化代码
注意事项:
1. 类只支持单继承, 不允许多重继承, 一个类只能有一个直接父类
2. 多个类可以继承同一个父类
3. 可以多层继承( 父类继承其他父类)
4. 父类中的私有属性和方法不能被子类直接调用, 只能继承, 不能使用( 子类范围大于父类)
继承中变量的访问特点
查找顺序:
1. 子类局部
2. 子类成员
3. 父类成员
如果子类和父类中出现同名的成员变量, 根据就近原则, 本方法-- -> 本类-- -> 父类
Super关键词
this 用法 ( 本类对象的引用)
this . 变量名:
当本类局部变量和成员变量发生命名冲突时, this . 变量名表示成员变量
this . 方法名:
调用本类的成员方法
this ( 参数表) :
调用本类的其他构造方法( 参数表区分调用的构造方法) , 必须放在本类构造方法执行体语句的第一行
super 用法 ( 父类对象的引用)
super . 变量名:
调用父类中的成员变量
super . 方法名:
调用父类中的成员方法
super ( 参数表) :
调用父类的构造方法, 必须放在构造方法中执行体语句的第一行
作用:
引用: 父类对象
在子类中指定调用父类的构造方法
构造方法特点
1 子类的构造方法都会默认访问父类的无参构造方法
子类在初始化的时候有可能会使用到父类中的数据, 如果父类没有完成初始化, 子类将无法使用
2 通过构造super ( ) 访问父类的构造方法完成父类成员的初始化
3 Object 类是所有类直接或者间接父类, 如果编写的类没有指定父类, 那系统会默认继承Object 类, 也就是说Object 类的所有能被继承的属性和方法在其他类中都会有一份
4 如果一个构造方法中的第一个语句不是this , 也不是super , 系统会默认添加super ( ) 。默认调用父类的无参构造方法
方法重写(OverRide)
方法重写, 也叫方法覆盖
定义:
子类用特殊的方法实现替换掉父类继承给它的一般的方法实现
语法要求:
1. 访问修饰符相同, 或更宽泛
2. ( 返回值类型 方法名 参数表) 不变
3. 不能比父类抛出更多的异常
注意事项:
重写的注解: @Override
1. 私有的方法不能重写
2. 静态方法不能重写
3. 子类重写父类方法的时候访问权限必须大于等于父类
重写与重载
重载:
方法名相同, 参数表不同
重写( 方法覆盖) :
继承体系不同
子类出现了和父类一样的方法声明( 访问修饰符相同, 或更宽泛, 返回值类型、方法名、参数表不变, 不能比父类抛出更多的异常)
多态
定义:
多态是同一个行为具有多个不同表现形式或形态的能力
前提:
要有继承/ 实现关系
父类引用指向子类对象( Animal a = new Dog ( ) ; )
多态中成员访问的特点
构造方法:
与继承类似, 子类构造方法通过super ( ) 访问父类的构造方法
成员变量:
编译看父类, 运行看父类
成员方法:
编译看父类, 运行看子类
原因:成员方法有重写, 成员变量没有
多态总结
1. 对象类型不变
一个对象从创建好后实际类型不会变化.
2. 只能对引用调用其引用类型中声明的方法
只能调用直接父类或间接父类中属性和方法
3. 运行时会根据对象实际类型找子类重写之后的方法
当子类对象放进父类引用,该引用调用方法,如果子类重写了该方法,就调用子类的
多态优缺点
1. 提高代码的复用性
2. 屏蔽不同子类的差异
日常生活中, 针对父类使用较多( 简单理解为每个人都会吃饭, 睡觉. 但具体在某个人后怎么吃饭是特有的, 并不统一)
多态使用场景
1. 多态使用在方法参数上
m ( A ( 类名) a ( 变量名) ) 可以用A 或A 的任何子类对象作为参数
形参可以使父类引用 而实参可以传子类对象
public class Test {
public static void main ( String [ ] args) {
Dog d= new Dog ( ) ;
m1 ( d) ;
Cat c= new Cat ( ) ;
m1 ( c) ;
}
public static void m1 ( Animal a) {
a. eat ( )
}
public static void m1 ( Dog d) {
}
public static void m1 ( Cat c) {
}
}
class Animal {
public void eat ( ) { }
}
class Dog extends Animal {
public void eat ( ) {
System . out. println ( "骨头" ) ;
}
}
class Cat extends Animal {
public void eat ( ) {
System . out. println ( "鱼" ) ;
}
}
2. 多态用在方法的返回值上
A m ( ) ; 调用方法, 可以返回A 或A 的某个子类对象
public class Test {
public static void main ( String [ ] args) {
Animal a = m1 ( 1 ) ;
Animal a = m1 ( 3 ) ;
}
public static Animal m1 ( int a) {
if ( a== 1 ) {
return new Cat ( ) ;
}
return new Dog ( ) ;
}
}
class Animal {
public void eat ( ) {
}
}
class Dog extends Animal {
public void eat ( ) {
System . out. println ( "骨头" ) ;
}
}
class Cat extends Animal {
public void eat ( ) {
System . out. println ( "鱼" ) ;
}
}
多态中的转型
1. 子类引用赋值给父类引用 可以直接赋值( 小 -- -> 大)
2. 父类引用赋值给子类引用 必须强制类型转换( 大 -- -> 小)
注意:
对象类型必须保持一致
Animal d = new Dog ( ) ;
Animal c = ( Cat ) d;
以上情况转换会报错, 不遵循对象类型保持一致原则
instanceof 关键词使用:
public class Test {
public static void main ( String [ ] args) {
Animal a= new Dog ( ) ;
System . out. println ( a instanceof Dog ) ;
System . out. println ( a instanceof Cat ) ;
System . out. println ( a instanceof Animal ) ;
if ( a instanceof Dog ) {
Dog d= ( Dog ) a;
} else {
System . out. println ( "不是Dog,不能被转换" ) ;
}
}
}
class Animal {
public void eat ( ) { }
public void sleep ( ) {
System . out. println ( "sleep 8 hours" ) ;
}
}
class Dog extends Animal {
@Override
public void sleep ( ) {
System . out. println ( "sleep 6 hours" ) ;
}
public void shout ( ) { }
}
class Cat extends Animal {
}