文章目录
面向对象的特征之一 封装性
我们设计的程序追求:
1.高内聚:类的内部数据操作细节,自己完成,不允许外部干涉
2.低耦合:仅对外暴露少量的方法用于使用
1. 设计思想
隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用,提高系统的扩展性,可维护性。简单来说:就是该隐藏隐藏,该暴露暴露;
2. 问题引入
我们在创建对象之后,可通过 ”对象.属性“ 的方式对对象属性赋值,赋值操作受到数据类型和存储范围的制约,不受其他制约;
但在实际问题中,我们通常会有额外的限制,不能在声明时体现,只能通过方法进行限制条件的添加。同时要避免用户再使用“对象.属性”方式给属性赋值,需将属性私有化(private)
属性私有化后用set,get 方法给属性赋值和获得属性的值
private String name;//属性私有化
private int age;
public Girl(int age) {
this.age =age;
}
public void setName(String name) {//通过set方法设置属性赋值
this.name=name;
}
public String getName() {//通过get方法获得属性的值
return this.name;
}
3.封装性的体现
①将类的属性私有化(private)同时提供公有的方法(getXXX)来获取和设置(setXXX)属性的值;
② 私有方法
③单例模式(单独的一个实例,将构造器私有化)
④若不希望类在包外被调用,可以将类设置为缺省(默认)的
4.权限修饰配合封装性的体现
1.Java规定四种权限修饰符即
说明:对于class 类:权限修饰符只可以用public和default(缺省)
4种权限修饰符,可以修饰类及类内部结构,属性方法构造器,内部类;
面向对象的特征之二 继承性
1.继承性的好处
①减少了代码的冗余,提高了代码的复用性
②便于功能的扩展
③为多态性的使用,提供了前提
2.格式与体现
① 格式:class A extends B { }
A:子类,派生类(subclass)
B:父类,超类,基类(superclass)
②体现:
(1)一旦子类A继承父类B后,子类A中就获得了父类B中声明的所有的结构属性和方法;
特别的:父类中声明为private 的属性和方法,子类继承父类后,获得了父类中私有的结构,只是由于封装性的影响,使子类不能直接调用父类中的结构而已;
(2)子类继承父类后,还可以声明自己的属性和方法,实现功能的扩展;
3.Java中关于继承的规定
①一个类可以被多个子类继承
②一个类只能有一个父类(Java类的单继承性)
③子父类是相对的(多层继承)间接/直接
④子类直接继承父类 称为 直接父类
子类间接继承父类 称为 间接父类
⑤ 子类继承父类后,就获得了直接父类和间接父类的所有属性和方法;ctrl+t 显示继承结构
图示
4. Object类的理解(根父类)
①如果没有显式的声明一个类的父类,则此类继承于Java.lang.object 类
② 所有的Java类(除Java.lang.object类)都直接或间接的继承于Java.lang.object类;
③ 意味着所有的Java类都具有Java.lang.object类的功能
方法的重写(overwrite/override)
1.重写:子类继承父类后,可以对父类中同名同参的方法进行覆盖操作;
2.应用:重写之后,当创建子类的对象后。通过子类调用父类的同名同参的方法,实际执行的是子类重写父类的方法
3.规定
子类中的叫重写的方法 /父类中的叫被重写的方法
从方法的定义顺序来看
权限修饰符 返回值类型 方法名(形参列表)throw 异常类型{ }
① 子类重写的方法的权限不小于父类被重写方法的权限
特别的: 子类中不能重写父类中private修饰的方法
② 返回值类型
(1)父类中被重写的方法的返回值类型为void,则子类重写方法的返回值类型也只能是void
(2)父类中被重写的方法的返回值类型为基本数据类型,则子类重写方法的返回值类型也只能是和父类相同的基本数据类型
(3)父类中被重写的方法的返回值类型为A类 ,则子类重写方法的返回值类型可以是A类也可以是A类的子类
③子类重写的方法的方法名和形参列表与父类被重写方法的方法名和形参列表相同;
④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
注:子类和父类中的同名同参的方法,要么都声明为非static的(考虑重写)要么都声明为static(不是重写);
子类对象实例化的全过程
1.从结果上看(继承性):子类继承父类后,就获得了父类中声明的所有属性和方法;即在创建子类对象时,在堆空间中,就会加载所有父类中声明的属性;
2.从过程上看:当我们通过子类的构造器创建对象时,一定会直接或间接的调用父类的构造器,进而调用父类的父类的构造器。直到调用了 Java.lang.object类中的构造器为止,正因为加载过所有的父类构造器,所以在内存中有父类中的结构,子类对象才可以考虑调用。
明确:在创建子类对象中,调用了父类的构造器,但自始至终就创建了一个对象;即该子类对象;
面向对象的特征之三 多态性
1.理解多态性
一个事物的多种形态
2.何为多态性
父类的引用指向子类的对象(子类的对象赋给父类的引用)
public class Person{
String name;
int age;
public void eat(){
System.out.print("吃饭”);
}
}
class Man extends Person{
public void eat(){
System.out.print("吃大碗饭”);
}
public void sleep(){
System.out.print("睡觉”);
}
}
public static void main(String[] args){
Person p1=new Man();//父类的引用指向子类的对象
Man p2=(Man)p1;//向下转型 强制转换
}
3.多态的使用
① 当调用子父类同名同参数的方法时,执行的是子类重写父类的方法–虚拟方法的调用;
②有对象的多态性后,编译期只能调用父类中声明的方法,运行期,实际执行的是子类重写父类的方法;
总结:编译看左,运行看右;
具体说明:
若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类中的同名方法,系统不可能把父类里的方法转移到子类中(编译看左,运行看右)
练习
public class InterviewTest {
public static void main(String[] args) {
Base1 base=new Sub1();
base.add(1,2,3);//sub_1
Sub1 s=(Sub1)base;
s.add(1, 2,3);//sub_2
}
}
class Base1{
public void add(int a,int...arr) {
System.out.println("base1");
}
}
class Sub1 extends Base1{
public void add(int a,int[] arr) {
System.out.println("sub_1");
}
public void add(int a,int b,int c) {
System.out.println("sub_2");
}
}
4.多态性使用的前提
①类的继承关系(没有继承就没有多态)
②方法的重写
说明:对象的多态性,只适用于方法,不适用于属性(编译运行时都看左边)
具体解释:对于实例变量则不存在重写覆盖,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量(编译运行都看左边)
继承成员变量与继承方法的区别
public class FieldMethodTest {
public static void main(String[] args) {
Sub s=new Sub();
System.out.println(s.count);//20
s.display();//20
Base b=s;
//引用数据类型比较时,是看地址值是否相同
System.out.println(b==s);//true
System.out.println(b.count);//12
b.display();//20
}
}
class Base {
int count =12;
public void display() {
System.out.println(this.count);
}
}
class Sub extends Base{
int count =20;
public void display() {
System.out.println(this.count);
}
}