一切皆对象,软件系统的运行就是依靠对象和对象之间传递消息来推进,所以设计软件,就是设计对象和对象之间的关系。而对象是一组状态和一系列行为的组合体。状态是对象的内在特性,行为是对象的外在特性。通过类来描述一类对象。
我们将数据和方法包装到一个类中,并隐藏具体的实现称为封装。封装的结果是同时带有特征和行为的数据类型。
java中对封装的支持:访问控制修饰符(public、protected、(default)、private)。我们通过使用访问控制修饰符来实现封装。只将想要暴露的地方暴露给用户,其他地方都隐藏起来。按照约定暴露的地方不予修改(如果已经被用户使用了),其他的地方是用户访问不到的,那么就可以需求重构和修改。
java中的访问控制权限 ,首先说明一点,为什么java提供了4个访问权限修饰符。如果只需要暴露和隐藏,那么只需要两个即可。我在前面提到用户,用户也就是使用者。但是用户也是相对的。对一个类来说,使用它的其他类就是该类的用户,对一个框架来说,使用了该框架的程序也是用户。所以针对不同的用户级别,java设计了四个访问修饰符来确保安全性,从小到类,大到框架都有设置
public:接口访问权限,顾名思义这就是暴露的部分,如果一个类的成员有该修饰符修饰,那么所有用户均可访问该成员。
private:私人访问权限,这个修饰符隐藏了成员(包括变量和方法),对所有用户均隐藏,仅在类的内部访问。
(default):包访问权限,java中提供包机制,不仅将具有内在逻辑的类包装在一起,也解决了另人头疼的命名空间问题。包访问权限,对同一个包中的用户来说是可以访问的,对于其他包中用户是隐藏的。
protected:继承访问权限,继承访问权限为了继承机制设计的修饰符。子类是父类的用户,这个用户有些特殊,他不像其他用户一般,继承的耦合性很强。如果一个类中的成员,不希望其他包中的用户访问,但是希望子类能够访问。如果子类在本包中其实包访问权限就够。但在其他包中显然不行,而接口访问权限范围太广也不行,所以使用继承访问权限。使得在其他包中的子类也能够访问父类的成员。
java设计的四个访问修饰符,覆盖了方方面面,不同的用户级别都能够实现隐藏效果。
封装提供了安全性,再也不用担忧用户将我的成员修改了,也不用担心重构时候哪些地方被用户使用了,哪些地方没有使用,因为已经知道暴露的是什么,隐藏的是什么了。
继承是面向对象设计的一个重要特性,非常强大。如果仅仅体现在代码复用这块,那么其实继承还没组合灵活好用。继承的强大体现在子类是父类,在继承树中,子类可以作为任一层父类使用,具体体现在,将子类的对象引用当作父类的对象引用,代码体现,左父右子,将子类的对象引用赋值给父类的对象引用。这给多态特性打下了基础。
java显然也提供了继承技术支持,使用extends关键字,可以表示两个类的关联关系,其他的则不需要我们考虑了,要明确一点,继承并不是将父类代码拷贝到子类中,这显然是违反了代码复用原则。其实在创建子类对象的时候,会创建一个父类的子对象,父类子对象和父类对象并没有什么区别,只不过父类子对象是在是在子类对象内部。
回到封装,java通过四个关键字来保证封装的安全性,继承和一般的关联不同,所以java提供了protected关键字来解决继承中的封装问题。我们知道private的修饰的成员是不能够被子类访问的(注意:子类继承了父类的所有,往往有人用不了父类中的成员,就认为没有继承下来,其实全部都在父类子对象中,不过因为权限不够,隐藏起来了)。因为对父类来说,子类就是用户,当然不能访问私人访问权限。protected关键字就解决了子类访问父类成员的问题,不管子类在何处都能访问。
多态是什么? 同一个行为的有不同的表现形式,也就是说,多态是不同的表现形式。而且只对对象的行为有意义。通俗点说就是只有对象的成员方法才能产生多态效果。
java显然也提供了多态技术支持,java提供了后期绑定技术(运行期绑定技术),所谓的绑定是指将一个方法调用和方法主体关联,那么后期绑定也就是,在编译期,编译器并不知道调用的方法是关联那个方法主体。等到运行的时候根据对象类型将方法名和方法主体关联起来。
第二个技术就是转型了,这一点就是继承提供的机制。左父右子这种形态,根据传入不同的子类对象,则就会调用不同的子类对象方法,从而实现多态。
我们知道了java中的方法都是动态绑定的,那么我们只需要编写与父类打交道的代码就好了,但是对于static,final修饰的方法并不是动态绑定的。static用来表示与类相关,类方法是前期绑定(编译期绑定),而final修饰的方法,不仅表示不能被子类重写,也表示关闭了动态绑定。所以在接口中,我们是不能够使用final关键字的,不合符接口的设计原则。
左父右子,父引用变量调用的非static和final方法(动态绑定)都是根据右边对象的类型来调相应的方法体,这就是多态的体现。
所以,为什么调用类方法和成员变量只会用父类中的,因为这并没有多态。