面向对象高级特性
继承【掌握】
继承是面向对象最显著的一个特征。继承是从已有的类中派生出新的类,新的类能拥有已有类的属性和行为。使用以存在的类的定义作基础建立新类的技术。新类可以增加新的数据或者新的功能,也可以用父类的功能,但不可以选择性的继承父类。继承的优点:复用性!
注意Java中,一个类只能有一个父类,不支持对基础!
继承的语法和规则
java在定义一个类时,通过关键字extends继承一个已有的类,这就是继承。被继承的类称为父类,新的类称为子类。子类继承父类的所有方法和属性。
类的继承声明格式:
修饰符 class 子类名 extend 父类名
在继承关系中,子类可以得到父类的属性和方法,这是从父类继承来的。子类可以添加新的属性和方法,添加父类所没有的;子类可以重新定义父类的属性和方法,修改父类的属性和方法,为自己所用。
class Person{
String name;
int 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 property(){
System.out.println("我是一个父类");
}
public void property1(){
System.out.println("我是一个父类,我的方法子类可以继承。");
}
}
class Student extends Person{
public void property(){
System.out.println("我是一个子类,我可以继承父类的属性,且修改父类的方法。我的名字是:"+name+";我的年龄是:"+age+"我还可以继承父类的方法。");
}
}
public class Demo {
public static void main(String[] args) {
Person p = new Person();
p.property();
Student s = new Student();
s.getAge();
s.getName();
s.setAge(23);
s.setName("隔壁老王");
s.property();
s.property1();
}
}
继承的特点:
子类可以得到父类的方法和属性,这是从父类继承来的。
子类可以添加新的属性和方法,添加父类所没有的。
子类可以重新定义父类的属性和方法,修改父类的属性和方法,为自己所用。
封装【掌握】
封装把对象的所有组成部分组合在一起,封装定义程序如何引用对象的数据,封装实际上使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。 适当的封装可以让程式码更容易理解和维护,也加强了程式码的安全性。
类的属性和方法的可见修饰符
private | defailt | protected | public | |
---|---|---|---|---|
同一类 | √ | √ | √ | √ |
同一包中的类 | √ | √ | √ | |
不同包中的类 | √ | √ | ||
其他包中的类 | √ |
访问修饰符的应用:
class Access{
private int pri;
int def;
protected int pro;
public int pub;
private void get1(){
System.out.println("The method is private");
}
void get2(){
System.out.println("The method is defaul");
}
public void get3(){
System.out.println("The method is public");
}
protected void get4(){
System.out.println("The method is protected");
}
}
public class Text4 {
public static void main(String[] args) {
Access t = new Access();
System.out.println(t.def=23);
System.out.println(t.pro=23);
System.out.println(t.pub=34);
t.get2();
t.get3();
t.get3();
}
}
访问器方法
由于对象不能直接通过引用访问私有数据域(属性或方法),为了能够访问私有数据域,可以为私有数据域添加读取方法和设置方法。
读取:getter方法
public 返回值类型 get属性名(数据类型参数值){
return 属性名;
}
设置:setter方法
public void set属性名(数据类型参数值){
属性名 = 参数值;
}
多态【掌握】
多态的实现条件:
条件一:继承是实现多态的前提
条件二:子类必须重写父类的方法
条件三:父类引用指向子类对象
多态的使用场合:
把父类作为方法的形参,那么实参可以是该父类的任意子类对象。
把父类作为方法的返回值类型,那么返回值可以是该父类的任意子类对象。
class Animal{
String name;
public void eat(){
System.out.println("我是父类方法。。。");
}
}
class Dog extends Animal{
int age;
public void eat(){
System.out.println("子类重写父类的方法。。。");
}
}
class Admin{
public void feed(Animal a){
//这里为什么编译并运行通过呢?
//编译时,因为形参a对应的数据类型(Animal类)中包含eat()方法,所以编译通过!
//运行时,检查形参a对应的实际数据类型,我们发现此时a对应就是Dog对象,那么就调用Dog对象的eat()方法
a.eat();
}
}
public class Test3 {
public static void main(String[] args) {
Admin admin = new Admin();
Dog dog = (Dog)creatAnimal("Dog");
Animal a = new Dog();
a.eat();//父类的方法在重写后会被子类覆盖
dog.eat();
//保证调用Admin类中feed()的实参可以是任意Animal的子类对象!
admin.feed(dog);
}
//把父类作为方法的返回值类型,那么返回值可以是该父类的任意子类对象。
public static Animal creatAnimal(String name) {
if("Dog".equals(name)) {
return new Dog();
}
return null;
}
}
引用数据类型转换:
对数据没有任何改变,只是修改了访问权限!
向上转型(自动),父类引用指向子类对象。
语法:父类类型 对象 = 子类对象;
例如:Animal animal = new Dog();
优点:隐藏了子类类型,提高了代码的扩展性,多态本身就是向上转型的过程。
缺点:只能使用父类共性的内容,不能调用子类特有方法!
向下转型(手动),子类引用指向父类对象。
语法:子类类型 对象 = (子类类型)父类对象;
例如:Dog dog = (Dog)animal;
优点:向下转型之后,可以调用子类特有方法
缺点:执行向下转型的时候,可以会发生类型转换异常(java.lang.ClassCastException)。
instanceof
用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
instanceof编译时特点
右边的“类或接口”是左边“对象”的父类、本身类和子类时,编译通过,否则编译失败!
本身类:此处的本身类指的就是“编译时”对应的类。
Animal animal = new Tiger(); -->本身类就是Animal
instanceof运行时特点
当左边“对象”不为null的时候
右边的“类或接口”是左边“对象”的父类、本身类时,这是返回结果就是true。
右边的“类或接口”是左边“对象”的兄弟类、子类时,这是返回结果就是false。
本身类:此处的本身类指的就是“运行时”对应的类。
Animal animal = new Tiger(); -->本身类就是Tiger
当左边“对象”就是null的时候
如果左边“对象”为null,那么instanceof运算的结果就是false!
研究多态情况下操作成员变量和成员方法的特点
成员变量特点
编译时:编译看左边,也就是看“编译类型”中是否包含该成员变量!
运行时:运行看左边,也就是执行“编译类型”中的成员变量!
核心:编译和运行都看左边(编译类型)。
成员方法特点:
编译时:编译看左边,也就是看“编译类型”中是否包含该成员方法!
运行时:运行看右边,也就是执行“运行类型”中的成员方法!
核心:编译看左边(编译类型),运行看右边(运行类型)!