------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一,继承
继承概述
多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,
那么多个类无需再定义这些属性和行为,只要继承那个类即可。
通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名 {}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,
还可以定义自己的新成员.
继承的好处
1)提高了代码的复用性
多个类相同的成员可以放到同一个类中
2)提高了代码的维护性
如果功能的代码需要修改,修改一处即可
让类与类之间产生了关系,是多态的前提
其实这也是继承的一个弊端:类的耦合性很强
继承的特点
1),Java只支持单继承,不支持多继承。
一个类只能有一个父类,不可以有多个父类。
2),Java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
3)继承中类之间体现的是:”is a”的关系
继承的注意事项
1)子类只能继承父类所有非私有的成员(成员方法和成员变量)
其实这也体现了继承的另一个弊端:打破了封装性.
2)子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。
3)不要为了部分功能而去继承.
示例:
class Fu{
int num=4;
}
class Zi extends Fu{
int num=5;
void show(){
System.out.println(num);
}
}
class ExtendsDemo{
public static void main(String[]args){
Zi z=new Zi();
z.show();
}
}
结论:示例:访问成员变量时
class Fu{
int num=4;
}
class Zi extends Fu{
int num=5;
void show(){
//第一个输出为5,第二个输出为4
System.out.println(this.num+" "+super.num);
}
}
class ExtendsDemo{
public static void main(String[]args){
Zi z=new Zi();
z.show();
}
}
一定要注意:
super(…)或者this(….)必须出现在第一条语句上
否则,就会有父类数据的多次初始化.
示例:
class Fu{
public int num = 10;
public Fu(){
System.out.println("fu");
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi");
}
public void show(){
int num = 30;
//输出30
System.out.println(num);
//输出20
System.out.println(this.num);
//输出10
System.out.println(super.num);
}
}
class Test {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
方法重写概述
/*
子父类中构造函数对对象的初始化过程
内存中的方法区位置的所有方法,是在程序编译时进驻内存的.
所以在运行时没有"方法存在的先后"之说,只有"方法被调用的先后"之说.
*/
class Fu{
Fu(){
show(); //会调用子类中的show(), 原因是子类覆盖了父类.
}
void show(){
System.out.println("fu show");
}
}
class Zi extends Fu{
int num=8;
Zi(){
super();//这条是隐式语句
System.out.println("在子类中的"+num);
}
void show(){
System.out.println("zi show"+num);
}
class ExtendsDemo{
public static void main(String[]args){
//Fu f=new Fu();// 执行这条语句时, 不存在继承,更不存在覆盖的机制,
//所以打印出 "fu show"
Zi z=new Zi();// 输出结果为{ zi show 0 第二行为 在子类中的 8 }
//原因是对子类进行初始化时,必须在对父类进行初始化完成后,才对子类初始化.
//z.show();
}
}
结论:
class Fu{
public int print(int x){
System.out.println("fu"+x);
return x;
}
}
class Zi extends Fu{
public int print(int x){
System.out.println("zi");
return x;
}
}
class FugaiDemo{
public static void main(String[] args){
Zi z=new Zi();
z.print(5);
}
}
/*
静态成员变量,有默认值
静态不能直接访问非静态 为什么呢
生命周期 静态优先非静态,静态成员调用的时候,还没有对象
静态方法中,不能写this也不能写super
*/
class Student
{
String name;
int age ;
//静态区,无论new多少对象,只有一个
static String country ;
public static void show(){
System.out.println(country);
}
public void method(){
System.out.println(name+age+country);
}
}
class StaticDemo1
{
public static void main(String[] args)
{
Student.show();
//System.out.println(Student.country);
}
}
//父类为抽象类
abstract class Animal{
public abstract void eat();
}
//
class Cat extends Animal{
public void eat(){
System.out.println("猫爱吃鱼");
}
// 猫的特有方法
public void zhua(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗啃骨头");
}
public void count(){
System.out.println("狗算数");
}
}
class MaoDemo{
public static void main(String[]args){
method(new Dog());
method(new Cat());
}
//通过方法来实现,来什么动物,就打印什么动物的吃法.
public static void method(Animal a){ //此处省略了 Animal a = new Dog() 传递
a.eat();// 可被复写的方法(非子类特有方法)
//子类特有方法
if(a instanceof Cat){ // 判断父类引用是否指向Cat子类.
Cat c=(Cat)a;//向下转型(强制)
c.zhua();//子类特有方法
}
else if(a instanceof Dog){
Dog d=(Dog) a;
d.count();
}
}
}
class Fu{
void 讲课(){
System.out.println("管理");
}
void 钓鱼(){
System.out.println("钓鱼");
}
}
class Zi extends Fu{
void 讲课(){
System.out.println("java");
}
void 看电影(){
System.out.println("看电影");
}
}
class FZDemo{
public static void main(String []args){
Fu f=new Zi();
//Zi f=new Zi();
f.讲课();// 编译时,编译器发现父类中有讲课方法,所以编译通过.
//但是运行时,运行过程还是先从子类中找该方法,如果有就调用,没有再去父类调用.
f.看电影();// 是在编译时失败的. 原因是,编译器发现父类中根本没有看电影的方法(). 所以编译不通过.
f.钓鱼();
}
}
class Fu{
int num=7;
void show(){
System.out.println("fu");
}
}
class Zi extends Fu{
int num=9;
void show(){
System.out.println("zi");
}
}
class FziDemo{
public static void main(String[]args){
Fu f=new Zi();
//打印父类中的num, 因为有父类的标识
System.out.println(f.num);
//运行时,走子类重写的方法
f.show();
}
}