当前位置 : 主页 > 编程语言 > java >

继承,多态,抽象类,接口

来源:互联网 收集:自由互联 发布时间:2023-09-03
一,继承 1,概述 -多个类中存在相同的属性和行为时,把这些相同的内容提取到一个独立的类中 其他类就不用在重复定义这些内容,只需要通过extends关键字继承独立的类 class 子类 e

一,继承

1,概述

-多个类中存在相同的属性和行为时,把这些相同的内容提取到一个独立的类中

其他类就不用在重复定义这些内容,只需要通过extends关键字继承独立的类

class 子类 extends 父类{}

有了继承后,我们就可以在一个已经存在的类的基础上,继续扩展新的成员

class Student{

private String name;

private int age;

public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void eat(){}

}

class Teacher{

private String name;

private int age;

public Teacher() { } public Teacher(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void eat(){}

}

-我们发现上面2个代码成员变量 name,age一样

get和set方法也一样,吃睡方法也都一样

如果我继续定义工人类,医生类,。。。

他们也具备这些内容

每一次定义这样的类都要把这些重复内容定义一遍

非常麻烦,所以我们要想办法改进

-如何改进?

基本思路,把这些相同的内容提取出来单独存放到一个类中,只存一次

然后让其他类和这个单独的类产生一个关联,让这些类可以具备这些内容

而不用重复定义这些内容

-为了实现这样的效果,java就提供了一种技术: 继承

2,继承如何表示?

-我们把提取出来的类称为父类,基类,超类

-多个有重复内容的类称为,子类,派生类

-继承表示:使用关键字 extends

格式:

class Fu{}

class Zi extends Fu{}

package com.momo.demo;

public class Main {

public static void main(String[] args) {

Student s = new Student();

s.setAge(11);

s.setName("aaa");

System.out.println(s.getName()); System.out.println(s.getAge()); s.eat(); Teacher t = new Teacher("qwe",32); System.out.println(t.getName()); System.out.println(t.getAge()); t.eat(); }

}

//父类

class Person{

private String name;

private int age;

public Person() {

}

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public void eat(){

System.out.println("吃饭。。");

}

}

//子类

class Student extends Person{

public Student() {

}

public Student(String name, int age) {

super(name,age);

}

}

//子类

class Teacher extends Person{

public Teacher() {

}

public Teacher(String name, int age) {

super(name,age);

}

}

3,好处

-提高了代码的复用性

-提高了代码的维护性

-类和类产生了关系,这个关系是多态的前提

其实这也是个弊端,耦合度增加了

-原则:低耦合,高内聚

4,继承特点

-java只能单继承,不能多继承

一个类只能有一个父类,不能有多个父类

-java可以多层继承(继承体系结构)

class A{}

class B{}

class C extends A{}

class D extends B{}

//class E extends A,B{}

//class E extends A extends B{}

class A{}

class B extends A{}

class C extends B{}

class D extends C{}

package com.momo.demo;

public class Demo2 {

public static void main(String[] args) {

Son s = new Son();

s.fun();

s.show();

}

}

class Ye{

public void show(){

System.out.println("爷爷");

}

}

class Ba extends Ye{

public void fun(){

System.out.println("爸爸");

}

}

class Son extends Ba{

}

5,继承注意事项

-子类只能继承父类所有非私有的成员

-子类不能继承父类构造方法,但是可以通过super访问父类构造方法

-不要为了部分功能而去继承

-什么时候可以使用继承?

继承体现的是is a 的关系

Person

Student

Teacher

动物

package com.momo.demo;

public class Demo3 {

public static void main(String[] args) {

}

}

class Aaa{

public void show1(){}

public void show2(){}

}

/class Bbb{public void show2(){}public void show3(){}}/

/*

  • 发现bbb中出现了和aaa中一样的方法,所以就想用继承
  • 这样不好,这样不仅有了show2,还多了show1,可以这个show1并不是我们想要的
  • */

class Bbb extends Aaa{

public void show3(){}

}

package com.momo.demo;

public class Demo4 {

public static void main(String[] args) {

Sonn s = new Sonn();

s.fun();

s.show();

//s.method();找不到符号

}

}

class Fu{

private int a = 5;

public int b = 6;

private void method(){ System.out.println(a); System.out.println(b); } public void show(){ System.out.println(a); System.out.println(b); method(); }

}

class Sonn extends Fu{

public void fun(){

// System.out.println(a); a 在 com.momo.demo.Fu 中是 private 访问控制

System.out.println(b);

}

}

6,继承后成员变量的关系

-子类成员变量名和父类成员变量名不一样,这个简单

-子类成员变量名和父类成员变量名一样,在子类方法中访问的时候访问顺序是?

在子类方法中找,有就用

在子类成员位置找,有就用

在父类的成员位置找,有就用

如果还找不到,就报错(没有考虑父类的父类)

package com.momo.demo;

public class Demo5 {

public static void main(String[] args) {

Zi z = new Zi();

System.out.println(z.a);

System.out.println(z.b);

z.show();

}

}

class Father{

// public int a = 5;

public void fun(){

int a = 456;

}

}

class Zi extends Father{

// public int a = 555;

public int b = 6;

public void show(){ // int a = 55555; System.out.println(a); }

}

7,super关键字

-super的用法和this很像

this表示本类对象的引用

super表示父类对象的引用

-他们都有如下用法

访问成员变量

this.成员变量

super.成员变量

访问构造方法

this(...)

super(...)

访问成员方法

this.成员方法(...)

super.成员方法(...)

package com.momo.demo;

/*

  • 要访问子类成员a?
  • 要访问父类成员a?
  • */

public class Demo6 {

public static void main(String[] args) {

S s = new S();

s.show();

}

}

class F{

public int a = 5;

}

class S extends F{

public int a = 6;

public void show(){

int a = 7;

System.out.println(a);

System.out.println(this.a);

System.out.println(super.a);

}

}

8,继承后构造方法的关系

-子类中的所有构造方法默认都会访问父类的无参构造。为什么?

因为子类会继承父类中的数据,可能还要使用父类中的数据

所以子类初始化完成之前,一定要先完成父类数据的初始化

子类继承父类之后,子类中的所有构造方法第一句都是

super()

package com.momo.demo;

/*

  • 要访问子类成员a?
  • 要访问父类成员a?
  • */

public class Demo6 {

public static void main(String[] args) {

S s = new S();

//s.show();

S s2 = new S(123);

}

}

class F{

public F(){

System.out.println("父无参");

}

public F(int i){

System.out.println("父带参");

}

public int a = 5;

}

class S extends F{

public S(){

// super();

System.out.println("ZI无参");

}

public S(int i){

super();

System.out.println("ZI带参");

}

public int a = 6;

public void show(){

int a = 7;

System.out.println(a);

System.out.println(this.a);

System.out.println(super.a);

}

}

-如果父类中没有无参构造怎么办?

子类为什么要访问父类的构造方法?是为了完成父类数据初始化来供子类使用

既然没有无参构造,肯定有带参构造,那么就可以使用带参构造来显示完成

父类数据初始化操作。super(...)

通过super显示调用父类的带参构造

package com.momo.demo;

/*

  • 注意:super或this必须是第一条语句
  • */

public class Demo6 {

public static void main(String[] args) {

S s = new S();

//s.show();

S s2 = new S(123);

}

}

class F{

/* public F(){

System.out.println("父无参");

}*/

public F(int i){

System.out.println("父带参");

}

public int a = 5;

}

class S extends F{

public S(){

// super();

//super(123);

this(123);

System.out.println("ZI无参");

}

public S(int i){

super(123);

// super();

System.out.println("ZI带参");

}

public int a = 6;

public void show(){

int a = 7;

System.out.println(a);

System.out.println(this.a);

System.out.println(super.a);

}

}

package com.momo.demo;

/*

  • 子父类的初始化顺序
  • 代码块的执行顺序和次数
  • */

public class Demo7 {

public static void main(String[] args) {

Y y = new Y();

// y.show();

}

}

class X{

static{

System.out.println("帅哥");

}

{

System.out.println("美女");

}

public int a = 5;

public X(){

System.out.println("我");

}

}

class Y extends X{

static{

System.out.println("大长腿");

}

{

System.out.println("萝莉");//帅哥,大长腿,美女,我,萝莉,是,

}

public int a = 6;

public Y(){

System.out.println("是");

}

public void show(){

int a = 7;

System.out.println(a);

System.out.println(this.a);

System.out.println(super.a);

System.out.println("屌丝");

}

}

package com.momo.demo;

/*

  • 子父类的初始化顺序
  • 一个类的初始化过程
  • */

public class Demo8 {

public static void main(String[] args) {

c c = new c();

}

}

class a{

b b = new b();

a(){

System.out.println("a");

}

}

class b{

b(){

System.out.println("b");

}

}

class c extends a{

b b = new b();

c(){

System.out.println("c");

}

}

9,继承后成员方法的关系

-子类中的方法和父类中的方法不一样这个简单

-子类中的方法和父类中的方法一样,通过子类对象调用的时候

先在子类中找,有就用

在父类中找,有就用

还没有,就报错(没有考虑父类的父类)

package com.momo.demo;

public class Demo9 {

public static void main(String[] args) {

Zii z = new Zii();

z.fun();

z.show();

// z.aaa();

}

}

class Fa{

public void show(){

System.out.println("fushow");

}

}

class Zii extends Fa{

public void fun(){

System.out.println("zifun");

}

/* public void show(){

System.out.println("zishow");

}*/

}

10,方法重写

-上面案例中子类中出现了和父类中一摸一样的方法声明

的这种现象我们称为方法的重写(复写,覆盖)

-使用特点:

方法名不同,调用对应的

方法名相同,重写之后用的是子类自己的

-方法重写的应用

子类需要父类的功能,但是功能的主题子类有自己特有的内容的时候

我们就可以重写父类方法

这样既可以延续父类的功能,又可以定义自己特有的内容。

package com.momo.demo;

/*

  • 最早的手机只能打电话
  • 随着科技不断进步,现在已经研究除了很多新手机
  • 不仅仅可以打电话,还有很多其他功能
  • 在打电话的同时还可以干什么事情(显示通话时长,显示来电归属地信息...)

  • 我们按照分析定义了新手机类,重新编写了打电话方法,添加了功能
  • 但是不好,因为新手机是不是手机? 是手机,新手机应该继承手机类
  • 而且打电话的功能是手机本身就具备的基本功能
  • 这个功能在新手机中不用在重复编写,但是不编写这个代码,又大不了电话了。
  • 最终还是要加上这个功能,由于它继承了手机类,所以我们可以直接使用父类的功能即可
  • 通过super关键字调用父类已经实现过的功能,再去添加自己特有内容即可
  • / public class Demo10 { public static void main(String[] args) { NewPhone np = new NewPhone(); np.call("默默"); } } /
  • 定义一个手机类
  • */

class Phone{

public void call(String name){

//可能真正完成这个功能需要500行代码

System.out.println("给"+name+"打电话");

}

}

//新手机

class NewPhone extends Phone{

public void call(String name){

//System.out.println("给"+name+"打电话");

super.call(name);

System.out.println("通话时长");

System.out.println("归属地信息");

}

//很多其他功能

}

11,方法重写的注意事项

-父类中私有的方法不能被重写

私有的无法继承,谈不上重写

-子类重写父类方法时,访问权限不能更低,最好一致

-父类中的静态方法,子类也必须使用静态方法来重写

注意:这个本质上不是重写,只是现象上如此

package com.momo.demo2;

public class Demo1 {

public static void main(String[] args) {

Son s = new Son();

s.show();

s.fun();

}

}

class Father{

/* private void show(){

System.out.println("privatefushow");

}*/

/* public void show(){

System.out.println("fushow");

}*/

void show(){

System.out.println("fushow");

}

public static void fun(){

System.out.println("fustatic");

}

}

class Son extends Father{

/* private void show(){

System.out.println("privatezishow");

}//

public static void main(String[] args) {

Son s = new Son();

s.show();

}*/

//正在尝试分配更低的访问权限; 以前为public

/void show(){System.out.println("zishow");}/

public void show(){ System.out.println("zishow"); } // 被覆盖的方法为static /*public void fun(){ System.out.println("zistatic"); }*/ public static void fun(){ System.out.println("zistatic"); }

}

12,相关问题

-方法重写和重载的区别

-方法重载可以改变返回值类型码?重载跟返回值类型无关(两同一不同,同一类同一方法名,不同参数)

-this和super的区别以及用法

13,继承练习(标准代码)

-先分析在实现

分析:从具体到抽象的过程

实现:从抽象到具体的过程

-老师和学生案例

-猫和狗案例

分析:从具体到抽象的过程

猫:

成员变量:name,age,color

构造方法:无参,带参

成员方法:get和set,eat,sleep,抓老鼠

狗:

成员变量:name,age,color

构造方法:无参,带参

成员方法:get和set,eat,sleep,看门

共性内容:

成员变量:name,age,color

构造方法:无参,带参

成员方法:get和set,eat,sleep

提取一个父类---动物类

实现:从抽象到具体的过程

动物类:

成员变量:name,age,color

构造方法:无参,带参

成员方法:get和set,eat,sleep

猫继承动物:

构造方法:无参,带参

成员方法:抓老鼠

狗继承动物:

构造方法:无参,带参

成员方法:看门

测试:

无参+set方法

带参

//父类

class Person{

private String name;

private int age;

public Person() {

}

public Person(String name, int age) {

this.name = name;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public void eat(){

System.out.println("吃饭。。");

}

}

//子类

class Student extends Person{

public Student() {

}

public Student(String name, int age) {

super(name,age);

}

public void study(){}

}

//子类

class Teacher extends Person{

public Teacher() {

}

public Teacher(String name, int age) {

super(name,age);

}

public void teach(){}

}

day7,

7,final关键字

-继承中有个现象叫重写, 父类的功能就会被子类的覆盖掉。

有些时候不想让子类重写,为了实现这样的效果,java就带着final关键字来了。

-final最终的意思

可以修饰类,方法,变量

package com.momo.demo;

public class Demo8 {

public static void main(String[] args) {

Bb b = new Bb();

b.show();

}

}

class Aa{

public final void show(){

System.out.println("aaa");

}

}

class Bb extends Aa{

// 被覆盖的方法为final

/public void show(){System.out.println("bbb");}/

}

-修饰类:不能被继承

-修饰方法:方法不能被重写

-修饰变量:变成常量(自定义常量)

package com.momo.demo;

public class Demo8 {

public static void main(String[] args) {

/* Bb b = new Bb();

b.show();*/

int a = 5; a = 55; System.out.println(a); // final int b = 6; // b = 66;法为最终变量b分配值 final int b; b = 6; System.out.println(b); }

}

final class Aa{

public final void show(){

System.out.println("aaa");

}

}

//无法从最终com.momo.demo.Aa进行继承

/class Bb extends Aa{// 被覆盖的方法为final//public void show(){System.out.println("bbb");}//}/

8,相关问题

-final修饰变量的问题

基本类型:值不能变

引用类型:地址值不能变

package com.momo.demo;

public class Demo9 {

public static void main(String[] args) {

final int a = 5;

System.out.println(a);

final Cat c = new Cat(); System.out.println(c); // c = new Cat();无法为最终变量c分配值 // System.out.println(c); c.age = 22; System.out.println(c.age); }

}

class Cat{

int age = 11;

}

-final修饰成员变量的初始化时机(非静态的)

在对象构造完成之前即可

package com.momo.demo;

public class Demo9 {

public static void main(String[] args) {

final int a = 5;

System.out.println(a);

final Cat c = new Cat(); System.out.println(c); // c = new Cat();无法为最终变量c分配值 // System.out.println(c); //c.age = 22; System.out.println(c.age); // c.age = 33; 无法为最终变量age分配值 System.out.println(c.age); }

}

class Cat{ final int age; Cat(){ age = 22; // age = 22; } }

一,多态

1,概述

-同一事物在不同时刻表现出来的不同状态

-父类引用指向子类对象

人类

老师类

学生类

老师类 老师 = new 老师类(); 学生类 学生 = new 学生类(); //多态 人类 人 = new 老师类(); 人类 人 = new 学生类();

2,前提和体现

-前提:有继承关系

有方法重写(不重写没有意义了)

-体现:父类引用指向子类对象

package com.momo.demo;

public class Demo9 {

public static void main(String[] args) {

/* Cat c = new Cat();

c.eat();

Dog d = new Dog(); d.eat();*/ //多态 Animal a = new Cat(); a.eat(); a = new Dog(); a.eat(); }

}

class Animal{

public void eat(){

System.out.println("吃草");

}

}

class Cat extends Animal{

}

class Dog extends Animal{

}

3,多态下成员的访问特点

-成员变量

编译看父类,运行看父类

-构造方法

创建子类对象,访问父类构造。

-成员方法

编译看父类,运行看子类

-静态方法

编译看父类,运行也看父类

(静态和类相关)

package com.momo.test;

public class Demo1 {

public static void main(String[] args) {

/* Zi z = new Zi();

System.out.println(z.a);

System.out.println(z.b);

z.show();

z.method();

z.fun();*/

//多态 Fu f = new Zi(); System.out.println(f.a); // System.out.println(f.b);//找不到符号 f.show(); // f.method();找不到符号 f.fun(); }

}

class Fu{

Fu(){

System.out.println("aa");

}

public int a = 5;

public void show(){ System.out.println("fushwo"); } public static void fun(){ System.out.println("fustaticfun"); }

}

class Zi extends Fu{

Zi(){

System.out.println("bbb");

}

public int a = 55;

public int b = 66;

@Override public void show() { System.out.println("zishow"); } public void method(){ System.out.println("zimethod"); } public static void fun(){ System.out.println("zistaticfun"); }

}

4,多态的好处和弊端

-好处:

提高了复用性(继承)

提高了维护性(继承)

提高了扩展性(多态)

package com.momo.test;

public class Demo2 {

public static void main(String[] args) {

//我喜欢猫

Cat c1 = new Cat();

/* c1.eat();

c1.sleep();/// useCat(c1);// AnimalTools.useCat(c1);AnimalTools.useAnimal(c1);//我很喜欢猫,又养一只Cat c2 = new Cat();// AnimalTools.useCat(c2);// useCat(c2);/

c2.sleep();/AnimalTools.useAnimal(c2);//我非常喜欢猫,再养一只Cat c3 = new Cat();// AnimalTools.useCat(c3);/

c3.sleep();/// useCat(c3);AnimalTools.useAnimal(c3);//..../

* 问题:我养了很多猫,每次都创建对象 这个没有问题

* 问题在于调用方法,每次调用的都是一样的方法,只是对象名不一样。

* 所以需要改进。如何改进?

* 可以编写一个方法,通过这个方法去调用其他所有方法,参数就不不同的对象

*

* 有了方法后,就可以改进调用方法,调用简单了。

* */

System.out.println("--------------");

//我喜欢狗

Dog d1 = new Dog();

// AnimalTools.useDog(d1);

/*d1.eat();

d1.sleep();

/AnimalTools.useAnimal(d1);// useDog(d1);//我很喜欢狗Dog d2 = new Dog();//AnimalTools.useDog(d2);/

d2.sleep();*/

// useDog(d2);

AnimalTools.useAnimal(d2);

//出现和上面一样的问题,应该继续编写方法来改进调用方式

/* //使用狗对象所有方法的方法

public static void useDog(Dog d){

d.eat();

d.sleep();

}

//使用猫对象所有方法的方法

public static void useCat(Cat c){

c.eat();

c.sleep();

}//

* 根据分析,我们写了这2个方法,目前时再测试类中写的,合适码?

* 不合适。 应该写在哪里?

* 目前来说不管写在测试类,动物类,猫类,狗类 都不合适

* 因为这两个方法不是动物本身就具备的功能。

* 而是我们为了方便使用创建的快捷方法,是一种方便使用的工具。

*

* 所以我们应该额外定义一个工具类,来存储这些方法。

* 根据分析进行改进,改进后的调用方式就变了。

* /// AnimalTools.useDog(d1);// AnimalTools.useDog(d2);/

* 如果我后面又喜欢 ?? ,??,??,??,.... 这些动物

* 定义对应的类,继承动物类,重写对应的方法 这些都没有问题

* 每次为了方便使用还要再工具类中添加对应的use方法, 这个有问题

* 因为一旦出错,就会导致整个工具类无法使用。

* */

System.out.println("--------------");

Pig p = new Pig();

// AnimalTools.usePig(p);

AnimalTools.useAnimal(p);

}

}

class Animal{

String name;

String color;

String gender;

int age;

public void eat(){ System.out.println("吃"); } public void sleep(){ System.out.println("睡"); } public void show(){ System.out.println(name+"---"+age+"---"+color+"---"+gender); }

}

class Cat extends Animal{

public void eat(){

System.out.println("猫吃鱼");

}

public void sleep(){

System.out.println("猫蜷着睡");

}

}

class Dog extends Animal{

public void eat(){

System.out.println("狗吃骨头");

}

public void sleep(){

System.out.println("狗趴着睡");

}

}

class Pig extends Animal{

public void eat(){

System.out.println("??吃饲料");

}

public void sleep(){

System.out.println("??躺着睡");

}

}

//动物工具类

/*

  • 工具就是为了方便使用,方法就写成静态的
  • /

class AnimalTools{private AnimalTools(){}//使用狗对象所有方法的方法/

d.eat();

d.sleep();

}

//使用猫对象所有方法的方法

public static void useCat(Cat c){

c.eat();

c.sleep();

}

public static void usePig(Pig p){

//int a = "a";

p.eat();

p.sleep();

}*/

public static void useAnimal(Animal a){

//父类引用指向子类对象,,多态。。。

//Animal a = new Dog()

//Animal a = new Cat()

//Animal a = new Pig()

//Animal a = new She()

a.eat();

a.sleep();

}

}

-弊端:

多态情况下无法访问子类特有内容(弊端)

我就要访问怎么办?

创建子类对象

把父类的引用强转成子类的引用(向下转型)

向上转型

Fu f = new Zi();

向下转型

Zi z = (Zi)f;

注意:f必须是能够转换成Zi的

ClassCastException 类型转换异常

Animal a = new Cat(); Cat c = (Cat)a; c.eat(); a = new Dog(); //Dog d = (Dog)a; //ClassCastException 类型转换异常 // Cat cc = (Cat)a; // cc.eat(); // d.eat();

package com.momo.test;

public class Demo3 {

public static void main(String[] args) {

Father f = new Son();

f.show();

// f.fun();找不到符号

//向下转型 Son s = (Son)f; s.fun(); s.show(); }

}

class Father{

public void show(){

System.out.println("fushow");

}

}

class Son extends Father{

public void show(){

System.out.println("zishow");

}

public void fun(){ System.out.println("zifun"); }

}

5,多态练习(多态标准写法)

-老师和学生

-猫狗案例

package com.momo.test;

public class Demo4 {

public static void main(String[] args) {

/* A a = new B();

a.show();*/

B b = new C(); b.show(); }

}

class A{

public void show(){

show2();

}

public void show2(){

System.out.println("高");

}

}

class B extends A{

public void show() {

super.show();

}

@Override

public void show2() {

System.out.println("富");

}

}

class C extends B{

@Override

public void show() {

super.show();

}

@Override public void show2() { System.out.println("帅"); }

}

二,抽象类

1,概述

-前面案例提取出来的父类,不是一个具体的事物,不应该new

所以我们应该声明成抽象类。

-父类中的方法不应该给出具体的实现,也应该声明为抽象方法

2,特点

-抽象类,抽象方法都要用 abstract来修饰。

-抽象类中不一定有抽象方法,但是有抽象方法的类必须是抽象类

-抽象类本身不能实例化,但是可以依赖多态实现实例化---抽象类多态

通过具体的子类实现实例化

-抽象类的子类:

可以是抽象类,可以不重写抽象方法

也可以是具体类,必须重写父类中的所有抽象方法

package com.momo.test;

public class Demo5 {

public static void main(String[] args) {

//Catt s = new Catt();

// s.eat();

//抽象类多态 Anima p = new Dogg(); p.eat(); /* * 这个有问题, 我创建了一个动物对象 ,动物?到底是什么动物? * Animal a = new Animal(); * 动物?到底是什么动物? 不应该new 它不是一个具体的事物 * 它是一个抽象的事物,这个类应该是一个抽象类,抽象类也要用 abstract来修饰 * 只有具体的猫或这狗才是具体的事物。 * 不同的动物吃的不一样, 所以动物类中的eat方法不应该给出具体的实现 * 应该强制要求子类必须重写 ,如何实现? * java带着关键字 abstract 来了。 * 一个没有具体实现的方法(没有{方法体}方法)我们应该定义为抽象方法, 抽象方法要用abstract 修饰 * 一个类中如果有了抽象方法,这个类也应该定义为抽象类。 * */ // Anima pp = new Anima(); com.momo.test.Anima是抽象的; 无法实例化 //pp.eat(); }

}

abstract class Anima{

/* public void eat(){

System.out.println("吃");

}*/

//没有方法体的方法要定义为抽象方法

public abstract void eat();

}

abstract class Catt extends Anima{

/* public void eat(){

System.out.println("猫吃鱼");

}*/

}

class Dogg extends Anima{

public void eat(){

System.out.println("狗吃骨头");

}

}

3,抽象类的成员特点

-成员变量

可以是变量,也可以是常量

-构造方法

有,但是不能造对象

用于子类访问父类数据初始化的。

-成员方法

抽象的,要求子类必须做的

非抽象的,给子类继承的,提高复用性

package com.momo.test;

public class Demo6 {

public static void main(String[] args) {

Animall aa = new Tiger();

System.out.println(aa.a);

aa.a = 55;

System.out.println(aa.a);

System.out.println(aa.b);

aa.fun();

aa.show();

// Animall a = new Animall();com.momo.test.Animall是抽象的; 无法实例化 }

}

abstract class Animall{

int a = 5;

final int b = 6;

Animall(){ System.out.println("wucan"); } Animall(int a){ System.out.println("daican"); } abstract void show(); public void fun(){ System.out.println("aaa"); }

}

class Tiger extends Animall{

@Override void show() { System.out.println("dfdfd"); }

}

4,抽象类练习

-猫狗案例

分析:从具体到抽象

具体事物:猫和狗

猫:

成员变量:姓名,年龄,颜色。。。

构造方法:无参,带参

成员方法:get,set,eat,sleep, catchMouse。show。。。

狗:

成员变量:姓名,年龄,颜色。。。

构造方法:无参,带参

成员方法:get,set,eat,sleep, lookDoor。show。。。

有共性内容,提取父类动物类,不同的动物吃的不一样,吃应该是抽象的, 那么这个类也应该是抽象类。 抽象动物类: 成员变量:姓名,年龄,颜色。。。 构造方法:无参,带参 成员方法:get,set,abstract eat(),sleep, show。。。 实现:从抽象到具体 定义抽象动物类 成员变量:姓名,年龄,颜色。。。 构造方法:无参,带参 成员方法:get,set,abstract eat(),sleep, show。。。 狗类继承动物类 成员变量: 构造方法:无参,带参 成员方法:重写eat ,添加 lookDoor。 猫类继承动物类 成员变量: 构造方法:无参,带参 成员方法:重写eat ,添加 catchMouse 测试类测试: 具体类测试: 无参+set 带参 多态测试:向下转型 无参+set 带参

-老师和学生案例

-我们要设计一个员工系统,需要对员工类进行设计,

员工包含3个属性:工号,姓名,工资

经理也是员工,除了上面3个属性之外,还多了一个奖金属性

请使用继承思想设计员工类和经理类,提供必要的方法可以进行属性访问

并测试。。。

5,抽象类的相关问题

-一个类如果没有抽象方法,可以定义为抽象类码?有什么意义?

-抽象关键字不能和哪些关键字共存?

private 冲突 非法的修饰符组合: abstract和private

final 冲突 非法的修饰符组合: abstract和final

static 冲突 非法的修饰符组合: abstract和static


三,接口

1,概述

-前面的猫狗案例,猫狗除了吃睡玩,然后就是看门,抓老鼠。

现在社会中有中职业驯兽师,可以训练出会钻火圈的猫,会计算的狗,....

这些额外的功能不是动物本身就具备的,是训练出来的,所以这些功能

不能定义到动物类中,所以为了体现事物的扩展性,java就提供了接口

来定义这些扩展功能,再接口中这些功能不能给出具体的实现(不同动物训练方式不一样)

将来哪些具体的动物被训练了,这部分动物去实现接口中的这些功能即可

2,特点

-定义接口使用关键字 interface

格式: interface 接口名{}

-实现接口用 implements 关键字

格式:class 类名 implements 接口名{}

-接口本身不能实例化

但是可以依赖具体的实现类实现实例化---接口多态

具体类多态:几乎不用

抽象类多态:常用

接口多态:常用

-接口的实现类

可以是抽象类,可以不重写, 意义不大

可以是具体类,必须重写所有抽象方法

package com.momo.test;

public class Demo7 {

public static void main(String[] args) {

//com.momo.test.AniamlInterface是抽象的; 无法实例化

//AniamlInterface ai = new AniamlInterface();

//接口多态

AniamlInterface ai = new Snake();

ai.fireCircle();

ai.fun();

//ai.show();找不到符号

Snake ss = (Snake) ai; ss.show(); }

}

interface AniamlInterface{

//接口抽象方法不能带有主体

/* public void fireCircle(){

System.out.println("钻火圈");

}*/

//接口中的方法有默认修饰符 public abstract 但是建议自己写上 void fireCircle(); public abstract void fun();

}

abstract class Lion implements AniamlInterface{

}

class Snake implements AniamlInterface{

@Override public void fireCircle() { System.out.println("bbb"); } @Override public void fun() { System.out.println("aaa"); } public void show(){ System.out.println("adf"); }

}

3,接口的成员

-成员变量:

只能是静态常量,有默认修饰符 public static final

-构造方法:

没有构造方法,接口用来定义扩展功能的

-成员方法:

有默认修饰符 public abstract

只能是抽象方法(针对我们自己定义的普通方法)

可以有默认的非抽象方法

可以有静态的非抽象方法

package com.momo.test;

public class Demo8 {

public static void main(String[] args) {

/* Inter i = new InterImp();

System.out.println(i.a);

// i.a = 55;无法为最终变量a分配值

System.out.println(i.a);

System.out.println(i.b);*/

//说明了 其实还有一个默认修饰符 static System.out.println(Inter.a); System.out.println(Inter.b); }

}

interface Inter{

int a = 5;//实际上不是一个变量,默认修饰符 final

final int b = 6;

public static final int c = 7;

//接口中的成员变量有默认修饰符 public static final ,接口中的成员变量只能是静态的常量

}

class InterImp implements Inter{

}

public class Demo7 {

public static void main(String[] args) {

AniamlInterface ai = new Snake();

ai.aaa();

// ai.bbb();

AniamlInterface.bbb(); }

}

interface AniamlInterface{

//接口抽象方法不能带有主体

/* public void fireCircle(){

System.out.println("钻火圈");

}*/

//接口中的方法有默认修饰符 public abstract 但是建议自己写上 void fireCircle(); public abstract void fun(); public default void aaa(){ System.out.println("接口默认方法"); } public static void bbb(){ System.out.println("接口静态方法"); }

}

class Snake implements AniamlInterface{

@Override public void fireCircle() { System.out.println("bbb"); } @Override public void fun() { System.out.println("aaa"); } public void show(){ System.out.println("adf"); }

}:

网友评论