1.继承
1.1概述
由来
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那一个类即可。如图所示:
生活中的继承
其中,多个类可以称为子类,单独那一个类称为父类、超类(superclass)或者基类。
定义
- 继承:就是子类继承父类的属性和行为,使得子类对象具有父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
好处
- 提高代码的复用性。
- 类与类之间产生了关系,是多态的前提。
私有属性是否可被继承
这个问题目前没有唯一的标准答案,网络上可以看到2种答案,分别是可继承和不可继承。
可以被继承,但是由于private的限制,所以在子类中不能直接访问。
不可以被继承。当构建子类对象时,首先创建父类对象,然后再创建子类对象,子类对象中包裹父类对象
子类除了拥有父类的属性和方法(拥有父类的所有成员,但是注意构造器和析构器不是成员),也可以创建自己的特性。
super:
super:当前的父类
this:代表当前的对象
注意:只能在自己本类使用
方法的覆盖(重写)Override
继承的关系中 方法名一样 参数一样 返回值类型一样(三同原则)。
object
object类是所有类的父类 创建的类都继承object类。
1.2继承的特点:
Java中不支持多重继承,Java中要求任何的子类只能有一个直系的双亲类。
子类可以重写父类的方法。
可以在子类中进行覆盖定义父类中的成员方法和成员属性。
Java支持多层继承(继承体系):C继承B,B继承A,就会出现继承体系。Java中的所有类都直接或者间接的集成于java.lang.Object.
提高了类之间的耦合性。
1.3继承的格式
通过extends关键字,可以声明一个子类继承另外一个父类,定义格式如下:
class 父类{
...
}
class 子类 extends 父类{
...
}
下面通过代码创建父类,子类继承父类,测试代码...
package extend;
public class fu {
public void show(){
System.out.println("我是父类show 方法");
}
//未提供构造方法,默认有一个无参构造方法
}
子类:
package extend;
public class zi extends fu{
public void show1(){
System.out.println("子类show 方法");
}
}
测试代码:
package extend;
public class test {
public static void main(String[] args){
//如果要调用fu类中的方法,就得创建父类对象
//这里用无参构造方法创建对象
fu f=new fu();
f.show();
//同理调用子类中的方法
zi z=new zi();
z.show1();
//子调用父类中的show方法
zi z_extend=new zi();
z_extend.show();
}
}
2.抽象
2.1抽象类
父类:public abstract class 自定义的类名(){}
子类:public class 子类名称 extends 自定义的类名(){}
定义格式
public interface 接口名称{
//抽象方法
//默认方法
//静态方法
//私有方法
}
含有抽象方法
抽象方法:使用 abstract 关键字修饰,可以省略,没有方法体。该方法供子类实现使用。
代码如下:
public interface InterFaceName{
public abstract void method()
}
含有默认方法和静态方法
默认方法:使用 default修饰,不可省略,供子类调用或者子类重写。
静态方法:使用static修饰,供接口直接调用。
代码如下:
public interface InterFaceName {
public default void method(){
// 执行语句
public static woid method2(){
// 执行语句
)
}
}
含有私有方法和私有静态方法
私有方法:使用private 修饰,供接口中的默认方法或者静态方法调用。
代码如下:
public interface InterFaceName{
private void method1(){
// 执行语句
}
private static void method2(){
// 执行语句
}
}
2.2抽象类的注意事项:
- 如果一个类中含有抽象方法,那这个类肯定是抽象类(且类和方法都必须用abstract修饰方法没有方法体)
- 抽象类中是可以不定义抽象方法
- 抽象类不能直接创建对象,必须通过子类实现
- 子类必须重写父类抽象方法
- abstract 不能与static、final斌并列修饰同一个方法(因为final修饰的方法是不能被重写的,但是abstract 修饰的方法必须要重写,冲突)
3.接口
接口
定义:所有的方法都是抽象的。
父类:public interface 自定义的接口名(){}
子类:public class 子类名称 implements 自定义的接口接口名(){}
属性
固定的修饰符修饰 public static final 相当于常量
方法
固定的修饰符修饰 public abstract ,无方法体
特点
- 不可以创建对象(因为是特殊的抽象类,因为抽象的方法没有任何意义)
- 子类需要重写接口中所有的抽象方法,子类就可以实例化
- 类可以实现接口(解决了继承的弊端)(可以new对象)
抽象类与接口的区别
- 抽象类中有构造方法,接口中无构造方法。
- 接口和接口之间支持多继承,类和类之间只能单继承。
- 一个类可以实现多个接口,但只能继承一个抽象类。
Java中可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。
default:(即默认,什么也不写):在同一包内可见。 使用对象:类、接口、变量、方法。
private:在同一类内可见。 使用对象:变量、方法。注意:不能修饰类(外部类)
public:对所有类可见。 使用对象:类、接口、变量、方法。
protected:对同一包内的类和所有子类可见。使用对象:变量、方法。注意:不能修饰类(外部类)
- public: 共有修饰符,所有类都可以访问,可以修饰类、数据成员、构造方法及方法成员
- private: 私有修饰符,只有在当前类中可以调用,可以修馆布数据成员、构造方法及方法成员,不可以修饰类
- protected: 保护修饰符,只有子类可以调用,可以修饰数据据成员、构造方法和方法成员,不可以修饰类
- default:(默认修饰符):只能被当前类或同包下被调用,类、方法、成员都可以使用默认权限,即不被private、 protected,public修饰
Java中,请说明final关键字的使用
final 表示最终的,可以修饰类、方法、变量
final 修饰类,表示此类为最终类,不能被继承
final 修饰方法,表示此方法为最终方法,不能被重写final 修饰变量,表示此变量为最终变量及常量
4.多态
4.1概述
引入
多态是继封装、继承之后,面向对象的第三大特性。
生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。
定义
多态: 是指同一行为,具有多个不同表现形式
前提(重点)
- 继承或者实现【二选一】
- 方法的重写【意义体现: 不重写,无意义】
- 父类引用指向子类对象【格式体现】
4.2多态的体现
多态体现的格式:
父类类型 变量名 new 子类对象;
变量名.方法名();
父类类型: 指子类对象继承的父类类型,或者实现的父接口类型。
代码如下:
Fu f = new Zi();
f.method();
那么为什么要用多态呢?具有两个好处:
1.应用程序不必为每一个派生类编写功能调用,只需要对抽象基类进行处理即可。大大提高程序的可复用性。//继承
2.派生类的功能可以被基类的方法或引用变量所调用,这叫向后兼容,可以提高可扩充性和可维护性。 //多态的真正作用.
代码如下:
定义父类:
public abstract class Animal {
public abstract void eat();
}
定义子类:
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
}
多态的特点:
对象类型和引用类型之间具有继承(类)/实现(接口)的关系;
引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定;
多态不能调用“只在子类存在但在父类不存在”的方法;
如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。
下面伪代码举例多态:
父类方法:a
子类方法:a,b
父类 A = new 子类();//多态
A.a();//执行的是子类方法
A.b();//会报错,因为父类没有方法b
(子类)A.b();//支持,把A强制转换为子类
4.3多态详解
面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。这是我们最后一个概念,也是最重要的知识点。
多态的定义:指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)
实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。
多态的作用:消除类型之间的耦合关系。
现实中,关于多态的例子不胜枚举。比方说按下 F1 键这个动作,如果当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;如果当前在 Word 下弹出的就是 Word 帮助;在 Windows 下弹出的就是 Windows 帮助和支持。同一个事件发生在不同的对象上会产生不同的结果。
4.4多态的好处:
1.可替换性(substitutability)。多态对已存在代码具有可替换性。例如,多态对圆Circle类工作,对其他任何圆形几何体,如圆环,也同样工作。
2.可扩充性(extensibility)。多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。实际上新加子类更容易获得多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。
3.接口性(interface-ability)。多态是超类通过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。如图8.3 所示。图中超类Shape规定了两个实现多态的接口方法,computeArea()以及computeVolume()。子类,如Circle和Sphere为了实现多态,完善或者覆盖这两个接口方法。
4.灵活性(flexibility)。它在应用中体现了灵活多样的操作,提高了使用效率。
5.简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
Java中多态的实现方式:接口实现,继承父类进行方法重写,同一个类中进行方法重载。
经典实例:
public class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
public class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
public class C extends B{
}
public class D extends B{
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
}
运行结果: