-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
一、继承
继承是面向对象的一个重要特征。当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继那个类即可。多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
通过extends关键字可以实现类与类的继承
class 子类名 extends 父类名 {}
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
有了继承以后,我们定义一个类的时候,可以在一个已经存在的类的基础上,还可以定义自己的新成员。
继承的好处:
提高了代码的复用性
多个类相同的成员可以放到同一个类中
提高了代码的维护性
如果功能的代码需要修改,修改一处即可
让类与类之间产生了关系,是多态的前提
其实这也是继承的一个弊端:类的耦合性很强
弊端
耦合性增强,违背了我们的开发原则
高内聚,低耦合
高内聚:能自己干的事儿从来不求别人
低耦合:类与类直接不要产生太多依赖
特点:
Java只支持单继承,不支持多继承。
一个类只能有一个父类,不可以有多个父类。
class SubDemo extends Demo{} //ok
class SubDemo extends Demo1,Demo2...//error
Java支持多层继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
注意事项:
父类私有成员,子类不能继承
子类不能继承父类构造方法
不要为了部分功能去继承
类与类之间存在 is a 关系时使用继承
演示用例:
class PersonTest{
public static void main(String[] args){
Student s = new Student("闯闯", 18,"czbk001");
System.out.println(s.name +"--" + s.age +"--"+ s.studyNum);
s.study();
s.eat(); // 继承来的
s.sleep(); //继承来的
Teacher t = new Teacher("老武", 48 ,"czbk008");
System.out.println(t.name +"--" + t.age +"--"+ t.workNum);
}
}
class Person{
String name ;//姓名
int age; //年龄
int money;
public void eat(){
System.out.println("下雨天 ,吃点热乎的 ");
}
public void sleep(){
System.out.println("下雨天 ,特别适合补一觉 ");
}
}
class Student extends Person{
String studyNum; //学号
Student(){}
Student(String name , int age, String studyNum){
this.name = name;
this.age = age;
this.studyNum = studyNum;
}
public void study(){
System.out.println("下雨天 , 好好学习");
}
}
class Teacher extends Person{
String workNum; //工号
Teacher(){}
Teacher(String name , int age, String workNum){
this.name = name;
this.age = age;
this.workNum = workNum;
}
public void work(){
System.out.println("下雨天 , 好好讲课");
}
}
成员变量的关系:
当父类与子类中变量名字不同时:调用对应的变量即可
当父类与子类中的变量名字相同 :
1.子类使用的子类自己的
2.子类想使用父类的变量,使用super关键字
this:前提是创建了当前对象 ,this 是当前对象的引用
super:没有创建父类对象,super可以理解为父类的引用,但其真正代表的是,父类存储空间的标识.
我们只需掌握:通过super关键字,子类可以访问到父类成员
演示用例:
class VarDemo{
public static void main(String[] args){
//创建子类对象
Zi z = new Zi();
z.show2();
System.out.println();
}
}
class Fu{
int num1 =30;
public void show(){
System.out.println(num1);
}
}
class Zi extends Fu{
int num1=20;
public void show2(){
int num1 = 10;
System.out.println(num1); //10
System.out.println(this.num1); //20
System.out.println(super.num1); //30
}
}
成员方法:
当方法名不同时,父类有的子类可以直接用
当方法名相同时,调用子类中的方法(子类和父类出现了一模一样的方法声明,包括 方法名,返回值类型,参数列表,这里,父类的方法会被子类的方法重写)
演示用例:
class AnimalTest{
public static void main(String[] args){
Animal a = new Animal();
a.eat();
Cat c = new Cat();
c.eat();
c.sleep();
Dog d = new Dog();
d.eat();
}
}
class Animal{
String name;
int leg;
private void sleep(){
System.out.println("号的睡眠是旺盛精力的保障哦!");
}
public void eat(){
System.out.println("吃饱饭才有力气战斗↖(^ω^)↗");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("小鱼儿,我的最爱。");//eat()方法重写
}
}
class Dog extends Animal{
public void eat(){
System.out.println("我不挑食的!");//eat()方法重写
}
}
注意事项:
1.父类私有的不能重写
2.子类重写的时候,权限不能更低
3.静态修饰的成员方法,只能用静态方法来重写
4.当你重写方法的时候,声明保持一致(返回值类型,方法名,参数列表);
Override(重写)和Overload(重载)的区别?
1.类的范围不一样
重写:子父类
重载:同一类
2.方法声明:
重写:返回值类型,方法名,参数列表 一模一样
重载:方法名一样,参数列表不同, 返回值类型无关
构造方法:
不能继承,但是我们可以调用父类的构造方法
子类的构造方法默认调用 父类的无参构造.
因为构造方法是给类初始化数据的,子类如果想使用父类的成员变量的值,那么必须用父类的先构造初始化.
注意事项:
1.父类中的成员变量被private修饰了,还得对外提供一个公共的访问方式.构造方法就是public的,那么子类想构造,就可以直接调用父类的构造方法了!
2.父类中没有无参构造
方式一:使用super中的有参构造
方式二:使用this中的有参构造,前提是有参构造也得访问到父类super有参构造中
3. super和this 必须在第一行,并且只能有一个
演示用例:
class Fu {
static {
System.out.println("静态代码块Fu");
}
{
System.out.println("构造代码块Fu");
}
public Fu() {
System.out.println("构造方法Fu");
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi");
}
{
System.out.println("构造代码块Zi");
}
public Zi() {
System.out.println("构造方法Zi");
}
}
class Test1{
public static void main(String[] args){
Zi z = new Zi();
}
}
参考结果:
---------- java ----------
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
输出完成 (耗时 0 秒) - 正常终止
Final:
Final关键字是最终的意思.
可以修饰类,成员变量,成员方法。
修饰类,类不能被继承,这样就可以避免被继承、被子类复写功能。
修饰变量,变量就变成了常量,只能被赋值一次
修饰方法,方法不能被重写
当在描述事物时,一些数据的出现值是固定的,那么这时为了增强阅读性,都给这些值起个名字。方便于阅读。而这个值不需要改变,所以加上final修饰。
作为常量:常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过_连接。
内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量。
抽象类
没有办法具体描述的类,比如 动物,水果 ,工具 ,蔬菜 , 情感....
格式:
类: abstract class 类名 { }
方法: public abstract void eat();
注意:抽象方法是没有方法体
抽象类中可以没有抽象方法 ,但是如果有抽象方法,那么此类必然为抽象类
抽象类的特点
1、抽象类和抽象方法必须用abstract关键字来修饰。
2、抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
3、抽象类不能实例化,也就是不可以用new创建对象。
抽象类是具体事物抽取出来的,本身是不具体的,没有对应的实例。
那么,抽象类如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
4、抽象类的子类
要么是抽象类
要么重写抽象类中的所有抽象方法
格式:修饰符abstract返回值类型 函数名(参数列表);
注:抽象类中可以有非抽象的方法。
下面通过一个实例,来说明抽象类的使用:
演示用例:
具体事物:基础班老师,就业班老师
共性:姓名,年龄,讲课。
class AbstractTeacher{
public static void main(String[] args){
Teacher tr = new Basic_Teacher("XX",28);
tr.teach();
Teacher tr1 = new Obtain_Employment_Teacher("ZZ",33);
tr1.teach();
}
}
abstract class Teacher{//定义抽象类,类名为Teacher
private String name;//变量私有化
private int age;
Teacher(){}
Teacher(String name,int age){//有参构造
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public int getName(){
return age;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public abstract void teach();//抽象方法teach
}
class Basic_Teacher extends Teacher{//基础班老师类继承Teacher
Basic_Teacher(){}
Basic_Teacher(String name,int age){
super(name,age);
}
public void teach(){
System.out.println("讲基础知识");//重写teach
}
}
class Obtain_Employment_Teacher extends Teacher{//定义就业班教师类,继承Teacher
Obtain_Employment_Teacher(){}
Obtain_Employment_Teacher(String name,int age){
super(name,age);
}
public void teach(){
System.out.println("讲解WEB知识");//重写teach方法
}
}
abstract 不能和哪些关键字共存?
private 冲突 -- 对子类隐藏,无法被复写,而 abstract 必须让子类重写
final 冲突 -- 不能被重写,矛盾
static 无意义-- 类名调用,没有方法体,无意义
抽象类的成员特点
成员变量
可以是变量
也可以是常量
构造方法
有构造方法,但是不能实例化
那么,构造方法的作用是什么呢?
用于子类访问父类数据的初始化
成员方法
可以有抽象方法 限定子类必须完成某些动作
也可以有非抽象方法 提高代码服用性
接口
接口,本质就是一种规则。作用就是扩展类的功能。
格式为:
interface 接口名{}
相当于定义了规则
接口中可以写方法,但是必须是抽象的.
Class 子类名 implements接口名{}
相当于给类扩展了接口的功能,需要重写接口的所有抽象方法
接口特点
接口用关键字interface表示
格式:interface 接口名 {}
类实现接口用implements表示
格式:class 类名 implements 接口名 { }
接口不能实例化
那么,接口如何实例化呢?
按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态。
接口的子类
要么是抽象类
要么重写接口中的所有抽象方法
接口成员特点:
成员变量
只能是常量
默认修饰符 public static final
构造方法
没有,因为接口主要是扩展功能的,而没有具体存在
成员方法
只能是抽象方法
默认修饰符 public abstract
类与类,类与接口以及接口与接口的关系:
类与类
继承关系,只能单继承,但是可以多层继承
类与接口
实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口。因为接口中的方法都是抽象的,都需要子类重写,所以可以多继承。
接口与接口
继承关系,可以单继承,也可以多继承。原因同上,都是因为接口中的类都是抽象的,需要被子类重写。
接口与抽象类的区别
成员区别
抽象类 变量,常量;有抽象方法;抽象方法,非抽象方法
接口 常量;抽象方法
关系区别
类与类 继承,单继承
类与接口 实现,单实现,多实现
接口与接口 继承,单继承,多继承
设计理念区别
抽象类 被继承体现的是:”is a”的关系。共性功能
接口 被实现体现的是:”like a”的关系。扩展功能
演示用例:
/*
动物类:姓名,年龄,吃饭,睡觉。(抽象)
动物培训接口:数数 (接口)
猫继承动物类
部分猫继承猫类并实现跳高接口
通过抽象类测试基本功能。
通过接口测试扩展功能。
*/
class CircusCatDemo{
public static void main(String[] args){
CircusCat cc = new CircusCat("加菲",4);
cc.fight();
cc.count();
cc.sleep();
cc.eat();
}
}
abstract class Animal{//定义抽象类,类名为Animal
private String name;
private int age;
Animal(String name,int age){
this.name = name;
this.age = age;
}
public void sleep(){
System.out.println("白天睡觉觉,晚上才是我的天下的说,喵~~~~");
}
public abstract void eat();//抽象方法 eat()
}
class Cat extends Animal{//定义猫类继承抽象类Animal
Cat(String name,int age){
super(name,age);
}
public void eat(){
System.out.println("还是鱼好吃啊");
}//重写抽象方法
}
interface Train{//定义训练接口
public abstract void count();//数数方法
}
interface Nature{//定义Nature接口
public abstract void fight();
public abstract void jump();
}
class CircusCat extends Cat implements Train,Nature{//定义马戏猫类继承猫类并实现Train和Nature接口
CircusCat(String name,int age){
super(name,age);
}
public void count(){
System.out.println("1,2,3,4,5,6真当我是白痴的吗,喵?");
}//重写接口方法
public void fight(){
System.out.println("我讨厌狗,猫的天敌不只是老鼠的说,喵~~~");
}
public abstract void jump(){
System.out.println("我跳的很高的,喵");
}
}
抽象类作为形式参数,要的是抽象类的子类对象
牌有很多种-- 麻将,三国杀,多米诺骨牌
所有我们牌定义为抽象类
接口作为形式参数,要的是实现了接口的子类对象
牌还有扩展功能 -- 变魔术
class PersonTest{
public static void main(String[] args){
//创建人的对象
Person p = new Person();
//创建纸牌的对象
Card c = new Card();
//p.play(c);
//创建牌的对象
//Pai pai = new Card();
Pai pai = new MaJiang();
p.play2(pai);
//变魔术
Magic m = new Card();
p.play3(m);
}
}
class Person{
//人打纸牌的方法
public void play(Card c){
c. bang();
c.shunzi();
}
//人玩牌
public void play2(Pai p){
p.fun();
}
//人用纸牌变魔术
public void play3(Magic m){
m.moShu();
}
}
//定义接口
interface Magic{
public abstract void moShu();
}
//抽象的牌类
abstract class Pai{
public abstract void fun();
}
//纸牌继承了 牌类, 实现了Magic接口
class Card extends Pai implements Magic{
//牌有炸的方法
public void bang(){
System.out.println("炸了, 翻倍...");
}
public void shunzi(){
System.out.println("顺出去,没了.....");
}
public void fun(){
System.out.println("打牌虽好,不要贪多哦!!!");
}
public void moShu(){
System.out.println("春晚,变魔术.....");
}
}
class MaJiang extends Pai{
public void fun(){
System.out.println("打麻将虽好,四圈差不多了");
}
}
返回值类型为 类 抽象类 接口
定义方法 修饰符 返回值类型 {
return 返回值
}
类作为返回值类型,返回的是类的对象
抽象类作为返回值类型,返回的是抽象类的子类对象
class FaPaiJiTest{
public static void main(String[] args){
//创建人对象
Person p = new Person();
FaPaiJi fpj = p.getFaPaiJi();
//Magic m = fpj.faPai3();
//Magic m = new Person().getFaPaiJi().faPai3(); //链式编程
new Person().getFaPaiJi().faPai3().moShu();
}
}
class Person{
//人使用 发牌机工作
public Card work(FaPaiJi fpj ){
Card c = fpj.faPai();
return c ;// Card
}
//人拿到发牌机
public FaPaiJi getFaPaiJi(){
return new FaPaiJi();
}
}
class FaPaiJi {
//发牌机发牌
public Card faPai(){
Card c = new Card();
return c;
}
public Pai faPai2(){
//返回的是抽象类的子类对象
Pai p = new Card(); //多态
return p;
}
public Magic faPai3(){
//返回的是接口的实现类的子类对象
Magic m = new Card(); //多态
return m;
}
}
//定义接口
interface Magic{
public abstract void moShu();
}
//定义牌类
abstract class Pai{
public abstract void fun();
}
//card 继承牌类 ,实现接口
class Card extends Pai implements Magic{
public void tongHuaShun(){
System.out.println("同花顺.....");
}
public void fun(){
System.out.println("玩牌好好玩~~~");
}
public void moShu(){
System.out.println("春晚,变魔术.....");
}
}
-----------android培训、java培训、java学习型技术博客、期待与您交流!------------