day07_继承(上)

继承概述:

示例:

/*
继承:
1.提高代码的复用性
2.让类与类之间产生了关系,有了这个关系,才有了多态的特性

注意:
千万不要为了获取其他类的功能,简化代码而继承
必须类与类之间有所属关系才可以继承.

 
在java语言中:java只支持单继承(一个孩纸只有一个父亲),不支持多继承

因为多继承 容易带来安全隐患:当多个父类中定义了
相同功能,而功能内容不相同,子类对象不能确定运行哪一个
例如:
class A
{
  public void show()
  {
   System.out.println("A");
  }
}
class B
{
  public void show()
  {
   System.out.println("B");
  }
}
class C  extends A,B//假设支持多继承
{
 ...
}
C c1=new C()
c1.show();

java保留这种机制,另一种体现形式完成-->多实现

java支持多层进程: A<—B<—C
*/

关于聚集,聚合和组合:
/*
聚集:has a 根据事物的紧密联系程度划分:
聚合:电脑和鼠标
组合:人的眼睛和人
*/

class Person 
{
   int age;
   String name;
}
class 
Student
 extends 
Person
//不能再继承其它类
{
   public void study()
    {
      System.out.println("good study");
    }
}
class 
Worker
 extends Person 
{

    public void study()
    {
      System.out.println(
"good job"
);
    }
}
/*
如何使用一个继承体系中的功能?
    想要使用体系,先查阅体系父类描述,因为父类中定义的是该体系中 共性功能
    通过了解共性功能,就可以知道体系的基本功能
    那么这个体系已经可以基本使用了
在具体调用时,要创建最子类的对象.
     A<-B<-C 创建C类对象
   ①有可能父类对象不能创建对象(抽象类,接口)
   ②创建子类对象可以使用更多功能(继承的和自有的)

-->查阅父类功能,创建子类对象使用功能
*/
   子父类出现后,类中成员特点:
1.变量
示例:
/*
子父类出现后,类成员特点:

类中成员:
1.变量
2.函数
3.构造函数

 -->变量
   如果子类中出现非私有的同名成员变量时
  子类访问本类中的变量->this
  子类访问父类中的同名变量-->super

super的使用和this使用几乎一致

this代表的是 本类对象的引用
super代表的是 父类对象的引用

*/
class Father
{
    int num=4;
}
class Son extends Father//当用到类Son,先加载类Father,再加载Son
{
     int num=5;
     void show()
    {
     System.out.println(num);//this.num->5
     System.out.println(super.num);//4
     /*
      如果注释掉 int num=5;
      则两者均输出4
      此时父类引用(super)也指向了子类对象new Son();(多态体现)
      堆内存中只有一个num
     */
    }
}
class ExtendsDemo
{
    public static void main(String[] args) 
    {
     Son s=new Son();
     s.show();
    }
}

子父变量重名

子父类变量重名在内存中:

重名变量在内存

2.函数
/*
2.子父类中的函数
  
  当子类出现和父类一模一样的函数时,
  当子类对象调用该函数,会运行 子类函数的内容
  如同父类的函数被覆盖一样.

这种情况是函数的另一个特性:重写(覆盖)
  注:父类的方法还在内存当中,只不过没有运行而已

覆盖:
①子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败

②静态只能覆盖静态.


覆盖和重载

重载:函数的参数个数和参数类型不同
覆盖:子父类方法一模一样(包括返回值类型)

重写一般用在:

当子类继承父类,沿袭了父类的功能,到子类中,
但是子类虽具备该功能,但是功能的内容却和父类不一致,
这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义
并重写功能内容.
例如:(简单对手机功能拓展)
class Tel
{
  void show()
  {
   System.out.println("number");
  }
}
class NewTel extends Tel
{
  void show()
  {
   super.show();
   System.out.println("name");
  }
}
*/
class Father
{
	 void show()
	{
	 System.out.println("Father's show");
	} 
}
class Son extends Father
{ 
	 void show()
	{
	 System.out.println("Son's show");
	}
}
class ExtendsDemo_2
{
	public static void main(String[] args) 
	{
	 Son s=new Son();
	 s.show();
	}
}

子父函数重名
 

3.构造函数

示例:

/*
-->理解为主
java继承中对构造函数是不继承的,只是调用(隐式或显式)。

子父类的构造函数.
   
   在对子类对象进行初始化时,父类的构造函数也会运行,并且先于子类的构造函数执行
   那是因为子类的构造函数默认第一行有一条隐式语句 super();
super():
   ①访问父类中的空参数的构造函数.
     子类中所有的构造函数第一行默认都是super();

   ②super语句一定定义在子类构造函数的第一行,
   那么在子类构造函数中this语句与super语句二者
   只能存在其一
  
  -->结论:
   ①子类的 所有构造函数,默认都会访问父类中空参数构造函数
     因为隐式super();存在
   
   ②当父类中没有空参数构造函数时,子类必须通过super语句手动指定
      父类中的构造函数
	
   ③当然,子类的构造函数第一行手动指定this语句来访问本类中的构造函数.
      此时隐式super();不存在.
    但是子类中(一定) 至少会有一个 构造函数会访问父类中的构造函数.
*/
class  Father //extends Object(所有类的父类)
{
	int number;
	Father()
	{
      //super();同样存在
	 number=20;
	 System.out.println("Father()");
	
	}
	Father(int x)
	{
	  System.out.println("Father(int x)");
	
	}
}
class Son extends Father
{
	Son()
	{
	  //super();//隐式语句

	  System.out.println("Son()"+"\t"+number);//Son()    20   
	
	}
	Son(int x)
	{
	 //super();//依然有
	 System.out.println("Son(int x)");
	}
}

class Extend_Construct
{
  public static void main(String[] args)
  {
    Son s=new Son();
	new Son(2);
	
  }
}

子父构造函数
/*
 为什么 子类中的构造函数 要访问 父类中的构造函数??
     因为父类中的数据子类可以直接获取. 
   所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的.

  如果要访问父类中指定的构造函数,通过super语句来手动指定
  class Person
{
  String name;
  Person(String name)
  {
   this.name=name;  
  
  }

}
class Student extends Person
{
  Student() 
 {
   super("zhangsan");
  System.out.println(name);//zhangsan
 }
}
class Extend_Construct
{
  public static void main(String[] args)
  {
	new Student();
  }
}

*/
 
super()语句为什么要放在第一行?
示例:
/*
为什么super语句要放在第一句?
  子类对象初始化时,如果先初始化自己,在去父类初始化,可能把子类的值覆盖掉
*/
class Person
{
  String name;
  Person(String name)
  {
    this.name=name;
    System.out.println(this.name);
}
class Student extends Person
{
 Student(String name) 
 {
  super("lisi");
  this.name=name;
  //super("lisi")如果能成功的话,lisi覆盖掉zhansan从而得不到想要的zhangsan
  System.out.println(this.name);
 }
}
class Extend_Construct
{
  public static void main(String[] args)
  {
	new Student("zhangsan");
  }

}
SuperFirst
final关键字:
示例:
/*
final:最终.作为一个修饰符
1.可以修饰,函数,变量

2.被final修饰的类不可以被继承
  继承的弊端:打破了封装,例如通过继承重写一些功能
  为了保证封装性,利用final关键字,让一些类不能继承.

3.被 final 修饰的功能不可以被复写(根据需要)

4.被 final 修饰的变量是一个常量只能赋值一次,既可以修饰成员变量,又可以修饰局部变量
  
  当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字.便于
  阅读.而这个值不需要改变,所以加上final修饰.例如:PI=3.1415926

5.内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量
  (当学习到内部类时,在看这一点)

*/
final class Demo//修饰类
{
   final int x=3;//修饰成员变量
   
   public static final double PI=3.14;//作为常量:所有字母都大写,多个单词下划线连接
                                      //权限够大(public),类名访问/对象之间共享(static),值不会变/常量(final)
   final void show()//修饰成员函数
	{}
   void show2()
	{
     final int y=4;//修饰局部变量
    
    }

}  
class DemoSon extends Demo//编译失败
{
}
 


 

 

 
 
原文地址:https://www.cnblogs.com/yiqiu2324/p/2870862.html