面向对象的特征一:封装与隐藏
我们程序设计追求“高内聚,低耦合”。
高内聚 :类的内部数据操作细节自己完成,不允许外部干涉;
低耦合 :仅对外暴露少量的方法用于使用。
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
当我们创建一个类的对象以后,我们可以通过"对象.属性
的方式,给对象的属性进行赋值。
这里,赋值操作要受到属性的数据类型和存储范围的制约。除此之外,没其他制约条件。
但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件。这个条件就不能在属性声明时体现,我们只能通过方法进行限制条件的添加。比如:调用属性set方法时,需要避免再使用对象.属性
的方式对属性进行赋值。则需要将属性声明为私有的(private)。此时,针对于属性就体现了封装性。
private
)同时,提供公共的(public
)get/set方法来获取权限从小到大顺序为:private < 缺省 < protected < public
注意区分default和protected,助记:protected可理解为孩子出远门需要保护
减少代码的冗余,便于功能的扩展,为之后多态性的使用提供了前提
extends
,即子类不是父类的子集, 而是对父类的扩展。//A:子类、派生类、subclass
//B:父类、超类、基类、superclass
class A extends B{}
get/set
方法操作私有属性super()
,即先调用父类的无参构造器,如果父类中没有无参构造,第一行必须显式的调用某一个有参构造为什么要单独说Object类,因为所有的java类(除java.lang.Object类之外)都直接或间接的继承于java.lang. Object类,如果我们没显式的声明一个类的父类的话,则此类继承于java.lang.Object类,通俗点说,这个类就是所有类的祖先,那这个类下的属性和方法其他类都可以使用,即变成了公共的方法。
Object类默认的基本方法有:
父类的引用指向子类的对象(或子类的对象赋给父类的引用),可以理解为一个事物的多种形态。
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,
运行时类型由实际赋给该变量的对象决定。
简 称:编译时,看左边;运行时,看右边
若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
//Dog是Animal的子类,最后运行的是子类重写后的方法
Animal animal = new Dog();
public void func(Animal animal){
animal.eat();
animal.shout();
}
对象的多态性,只适用于方法,不适用于属性,属性编译和运行都看左边
① 类的继承关系
② 方法的重写
使用强制类型转换符:()
instanceof
的判断,一旦返回true,就进行向下转型。如果返回false,不进行向下转型。a instanceof A:
判断对象a是否是类A的实例。如果是,返回true;如果不是,返回false。
Animal animal = new Dog()
if(animal instanceof Dog) //true
①谈谈你对多态性的理解?
实现代码的通用性。
深入理解:
当父类的引用变量指向子类对象时,被引用的子类对象的类型决定了调用谁的成员方法,引用变量决定可调用的方法。首先会去父类中寻找可调用的方法,找到了就执行子类中覆盖的该方法,就算子类中有现成的方法,同样也会先去父类中寻找,找到后执行重写的子类方法(这里的子类也就是最后决定调用的类方法)
②多态是编译时行为还是运行时行为?
of course 运行时行为
子类继承父类之后,可以对父类同名、同参的方法进行方法体的改写,覆盖父类
子类会从父类继承到权限内的属性和方法,且所有子类从父类继承过来的属性和方法都是相同的,重写可以对继承过来的方法进行改写而满足自己的需求,当创建子类对象后,通过子类对象调用重写过的方法时,实际执行的是子类重写的方法。
方法的声明:
权限修饰符 返回值类型 方法名(形参列表) (throws 异常的类型){
方法体
}
约定俗称:子类的叫重写的方法,父类中的叫被重写的方法
子类重写方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同
子类重写的方法的权限修饰符>=
父类被重写的方法的权限修饰符
返回值类型:
方法重写时,子类的返回值类型必须要 <=
父类的返回值类型。
方法重写时,子类抛出的异常类型要 <=
父类抛出的异常类型。
父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void
父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
父类被重写的方法的返回值类型是基本数据类型(比如:double),则子类重写的方法的返回值
类型必须是相同的基本数据类型(必须也是double)
特殊情况:子类不能重写父类中声明为private权限的方法,写了虽然不报错,但改写后的方法不构成重写,且调用的函数仍是父类的函数
子类与父类中同名同参数的方法必须同时声明为非static的;当声明为
static时不是重写,因为static方法是属于类的,子类无法覆盖父类的方法。
重写和重载的区别?
答:其实两个是完全不同的概念,知识名字相近而已。
重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了不同的方法。它们的调用地址在编译期就绑定了。Java的重载是可以包括父类和子类的,即子类可以重载父类的同名不同参数的方法。
所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,这称为“早绑定”或“静态绑定”;
而对于多态,只等到方法调用的那一刻,解释运行器才会确定所要调用的具体方法,这称为
super 关键字可以理解为:父类的
可以用来调用的结构:属性、方法、构造器
我们可以在子类的方法或构造器中。通过使用super.属性
或super.方法
的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯省略"super."
当子类和父类中定义了同名的属性或方法时,我们要想在子类中调用父类中声明的属性,则必须显式的使用super.属性
或super.方法
的方式,表明调用的是父类中声明的属性或方法。
this(参数列表)
或者super(参数列表)
语句指定调用本类或者父类中相应的构造器。同时,只能”二选一”,且必须放在构造器的首行super(形参列表)
的方式,调用父类中声明的指定的 构造器super(形参列表)
或 this(形参列表)
则默认调用的是父类中空参的构造器:super()
super(形参列表)
调用父类中的构造器此小节理解即可
从结果上看
从过程上看
当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类的构造器,……,直到调用了java.lang.Object类中空参的构造器为止。正因为加载了所有父类的结构,子类才可以继承父类的属性或方法
图示
注意
虽然创建子类对象时,调用了父类的构造器,但是自始至终就创建过一个对象,即为new的子类对象。
原文:https://www.cnblogs.com/silloutte/p/14589626.html