------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------
继承
一、特点
1,提高了代码的复用性。
2,让类与类之间产生关系,是多态性的前提。
注意:千万不要为了获取其他类的功能,简化代码而继承。必须是类与类之间有所属关系才可以继承。所属关系 is a。
class C
{
void demo1(){}
}
class A extends C
{
//void demo1(){}
void demo2(){}
}
class B extends C
{
//void demo1(){}
void demo3(){}
}
二、Java中的继承。
1,java只支持单继承,不支持多继承。为啥呢?答案:因为继承了多个父类如果有相同方法时 子类对象不确定运行哪一个。
2,Java还支持多层继承。A-->B--->C 原来可以形成继承体系。想要使用体系功能,"查阅父类功能,建立子类对象调用功能。"注解:父类的由来其实是由事物中的共性内容不断向上抽取而来的。所以父类中定义的是该体系中的最基本,最共性功能。继承出现后,代码上也有一些特点:
1,变量。
当子父类中定义了相同的名称的成员变量,子类要使用父类中的同名变量时,需要使用关键字super来区分。一般不会出现这种情况,因为父类中有了,子类不需要定义。而且父类定义时,一般变量都私有化。
2,函数。
子类可以直接访问父类中非私有的成员函数。特殊情况:当子类中定义了与父类一模一样的方法时,会发生覆盖操作。大多指的是非静态方法。 最终会运行子类的方法,父类相当于被覆盖了。 函数的另一个特性:覆盖(重写,复写)。什么时候用啊?当父类的功能要被修改时,不建议修改源码。因为是灾难。只要通过一个类继承原有类,定义一个新的升级后的功能即可。但是功能是相同的,只是实现方法改变。这是子类可以沿袭父类中的功能定义,并重写功能内容。这就是覆盖。覆盖很爽,但是有注意事项:
1,子类覆盖父类时,必须权限要大于等于父类权限。
2,静态不能覆盖非静态。
例题
class Fu
{
void show()
{
System.out.println("fu show");
}
void speak()
{
System.out.println("vb");
}
}
class Zi extends Fu
{
void speak()
{
System.out.println("java");
}
void show()
{
System.out.println("zi show");
}
}
class ExtendsDemo3
{
public static void main(String[] args)
{
Zi z = new Zi();
z.speak();
}
}
3,构造函数
构造函数可以本类进行对象初始化,也可以给子类对象进行初始化。
子类对象初始化过程:子类中的所有构造方法都会访问父类中空参数的构造函数因为每一个构造函数的第一行,都有一句隐式的super语句。
为什么要有这条语句?
因为子类会获取到父类中的数据,必须要先明确父类对数据的初始化过程。当父类中没有空参数构造函数时,子类构造函数必须通过super句来明确要访问的父类中指定的构造函数。当时子类构造函数也可以通过this语句访问本类中的构造函数。但是子类中肯定,至少有一个构造函数会访问父类。
例题
class Fu //extends Object
{
int num ;
Fu()
{
//super();
num= 60;
System.out.println("fu run");
}
Fu(int x)
{
System.out.println("fu ...."+x);
}
}
class Zi extends Fu
{
Zi()
{
super();
//super(4);
System.out.println("zi run");
}
Zi(int x)
{
this();
//super();
//super(3);
System.out.println("zi..."+x);
}
}
class ExtendsDemo4
{
public static void main(String[] args)
{
Zi z = new Zi(0);
System.out.println(z.num);
}
}
/*
class Person
{
private String name;
Person(String name)
{
this.name = name;
}
void show(){}
}
class Student extends Person
{
Student(String name)
{
super(name);
}
void method()
{
super.show();
}
}
*/
三、抽象类(abstract)
抽象类:其实就是在分析事物时,事物中的功能有些是不明确的内容的。这些不明确内容就是抽象的。可以通过抽象函数来描述。抽象函数一定要定义在抽象类中,因为,抽象函数所在类,也必须被抽象标识。
写法特点:
1,抽象函数只对函数进行声明,没有函数主体。
2,抽象类和抽象函数都需要用abstract修饰。
3,抽象类不可以进行实例化。
4,想要使用抽象功能,必须通过子类覆盖了父类中所有的抽象方法后,才可以对子类实例化。
如果只覆盖了部分抽象方法,那么子类还是一个抽象类。也可以理解为:抽象类是一个父类,是不断向上抽取而来的,在抽取过程中,只抽取了方法声明,但没有抽取方法实现。抽象类和一半类差不多。
区别:抽象类可以定义抽象方法。抽象类不可以建立对象。其实抽象类一样用于描述事物,既可以定义抽象方法,也可以定义非抽象方法。
abstract class Student
{
abstract final void study();
//abstract void study1();
void sleep()
{
System.out.println("躺着");
}
}
接口
初期理解:接口看上去是一个特殊的抽象类。里面存的都是抽象方法。
格式:
1,通过interface来定义。
2,接口中常见成员:常量,抽象方法。而且这些成员都有固定的修饰符。常量:public static final方法:public abstract
3,接口中的成员都是共有的。
4,一个类可以对接口进行多实现,也弥补了多继承带来的安全隐患,所以java对多继承进行了改良。用多实现方法来体现多继承的特性。
5,一个类可以继承一个类的同时,实现多个接口。6,接口与接口之间是继承关系,而且可以多继承。
应用特点:
1,接口是对外暴露的规则。
2,接口是功能的扩展。
3,接口的出现降低了耦合性。
抽象类和接口异同:相同:
1,都可以在内部定义抽象方法。
2,通常都在顶层。
3,都不可以实例化,都需要子类来实现。
不同点:
1,抽象类中可以定义抽象方法和非抽象方法,而接口中只能定义抽象方法。
2,接口的出现可以多实现。抽象类只能单继承。也就是说:接口的出现避免了单继承的局限性。
3,继承和实现的关系不一致。继承:is a,实现:like a
四、多态
表现:
1、父类或者接口的引用指向了或者接收了自己的子类对象。
2、前提:
(1)类与类之间要有关系。继承,实现。
(2)通常都会有覆盖。
3、好处:
预先定义的程序可以运行后期程序的内容。增强了程序的扩展性。
4、弊端:
虽然可以预先使用,但是只能访问父类中已有的功能,运行的是后期子类的功能内容。不能预先使用子类中定义的特有功能。
5、多态的注意事项:
在代码中。对于成员函数:Fu f = new Zi(); f.method();编译时期:看左边。运行时期:看右边。因为成员函数有一个覆盖操作。毕姥爷和毕老师的故事。对于非私有的实例变量,静态变量,静态方法。编译和运行都看左边。老师要求记住结论。有空闲时间,就想想为什么?
6、转型。
子类对象被父类引用:子类对象在向上转型。
将指向子类对象的父类应用转换成子类类型引用:向下转型。
毕姥爷和毕老师的故事。
class 毕姥爷{}
class 毕老师 extends 毕姥爷{}
毕姥爷 ly = new 毕老师();//毕老师向上转型为了毕姥爷。
向上转型 毕老师 ls = (毕老师)ly; //将代表毕老师对象的父类引用ly强制转换成了毕老师类型。向下转型。
7、应用电脑使用。
主板运行。
class MainBoard
{
public void run()
{
//主板运行;
}
public void usePCI(PCI p)//PCI p = new NetCard();
{
if(p!=null)
{
p.open();
p.close();
}
}
}
//为了提高主板功能的扩展性。
//定义了规则。让后期的出现的功能板块,只要覆盖该规则,就可以被这个主板使用。
interface PCI
{
void open();
void close();
}
class MainDemo
{
public static void main(String[] args)
{
MainBoard mb = new MainBoard();
mb.run(); mb.usePCI(null);
mb.usePCI(new NetCard());
}
}
class NetCard implements PCI
{
public void open(){}
public void close(){}
}
Object:是java中所有对象的直接或者间接的父类。它里面的方法都所有对象都具备的。
常见方法:
boolean equals(Object obj):用于比较两个对象是否相同。
String toString(): 获取对象的字符串表现形式 类名@哈希值 getClass().getName()+"@"+Integer.toHexString(hashCode());
Class getClass():获取正在运行的对象所属的字节码文件的对象。也就是说如果Demo d = new Demo();d.getClass():获取的就是d执行的对象所属的字节码文件Demo.class对象。通常在自定义对象时,因为对象中都有自己特有的描述,所以都会建立对象自身的特有比较方法,或者字符串表现形式。也就是说,会覆盖Object中的方法
/*
Demo d1 = new Demo();
Demo d2 = new Demo();
d1.getClass() == d2.getClass();
*/
class Demo //extends Object
{
public String toString()
{
this.getClass().getName()+"#"+Integer.toHexString(this.hashCode());
}
}
class Fu
{
void show()
{
System.out.println("fu show");
}
}
class Zi extends Fu
{
void function()
{
super.show();
//this.show();
}
void show()
{
System.out.println("zi show");
}
}