java学习第10天--abstract抽象|接口|多态


abstract抽象
什么是抽象类
由abstract修饰的方法叫抽象方法;由abstract修饰的类叫抽象类.抽象类是无法进行实例化(即具体的实现方法)的,因为他不是具体存在的类,或者说这样的类还不够完善,不能直接使用new关键字调用其构造器生成该类的对象.我们可以使用abstract定义一个抽象类和抽象方法.
抽象格式:
abstract class 类名{
//类体
public abstract void play();
}
抽象方法是没有方法体的, 需要注意的是在抽象类中既可以有抽象方法,也可以有普通方法,注意抽象方法是没有方法体的(也就是方法后面是没有大括号的)。凡是继承这个抽象类的实体子类,都必须要实现这个抽象方法。

abstract不能与final,static,private同时使用
当使用abstract修饰类时,表明这个类只能被继承;当使用abstract修饰方法时,表明这个方法必须由子类提供实现(即重写).而final修饰的类是不能被继承的,final修饰的方法不能被重写,因此final和abstract永远不能同时使用.
abstract不能用于修饰成员变量,不能用于修饰局部变量,,即没有抽象局部变量和抽象成员变量的说法;abstract不能用于修饰构造器,抽象类里定义的构造器只是普通构造器.
除此之外,当使用static修饰一个方法时,表明这个方法属于该类本身,即通过类就可调用该方法.但是如果该方法被定义为抽象方法,则将导致通过该类来调用该方法时出现错误(调用了一个没有方法体的方法肯定会引起错误).
abstract关键字修饰的方法必须被其自了哦重写才具有意义,否则这个方法将永远不会有方法体,因此abstract方法不能定义为private访问权限.

我们总结一下 抽象类的特点:
(1)抽象类不能被实例化
(2)构造方法 和 static 方法不能是抽象的
(3)父类的抽象方法往往在子类中实现
(4)抽象类可以具有指向子类对象的对象引用

抽象练习
1. 定义抽象类员工Employee,
(a)保护字段:姓名name,性别gender,年龄age等基本属性。
(b)定义抽象方法函数getsalary()表示领工资的操作
(c)定义普通函数whoami()输出 :我是+姓名
(d)拥有(姓名name,性别gender)参数的构造函数
定义一个经理类Manager 派生于员工;
(a)除了有员工等基本属性外,还有岗位级别 gree私有属性
(b)经理领7000元工资,打印并输出工资。
(c)重写父类的whoami(),调用父类的whoami()方法,再输出:我是一名经理。
定义一个会计类Accounting,派生于员工类;
(a)除了有员工等基本属性外,还有会计等级 rating私有属性
(b)会计领3000元工资,打印并输出工资。
(c)重写父类的whoami(),调用父类的whoami()方法,再输出:我是一名会计。
/**
* 定义类员工Employee,
*/
public abstract class Employee {
protected String name;
protected boolean gender;
protected int age;
public Employee(String name, boolean gender){
this. name=name;
this. gender=gender;
}
/**
* 表示领工资的操作
*/
public abstract void getsalary();
public void whoami(){
System.out.println( "我是" +name);
}
}
我们新建一个经理类Manager,继承Employee类,这时候Eclipse就提示我们必须要重写抽象方法getsalary。示例代码如下:
/**
* 经理类
*/
public class Manager extends Employee{
private String gree;
public Manager(String name, boolean gender){
super(name,gender);
}
//重写父类的抽象方法
public void getsalary(){
System.out.println( "经理领7000元工资" );
}

public void whoami(){
super.whoami(); //显示调用父类的方法
System.out.println( "我是经理" );
}
}
接下来是会计类。和上面的经理类差不多了。
/**
* 会计
*/
public class Accounting extends Employee {
private int rating;
public Accounting(String name, boolean gender) {
super(name, gender);
}
@Override
public void getsalary() {
System.out.println( "会计发3000工资" );
}
public void whoami() {
super.whoami(); // 显示调用父类的方法
System.out.println( "我是会计" );
}
}

2. 抽象类的多态
package com.oldboy_02;

/*
* 抽象类,抽象方法
* 抽象类:不能实例化,不能创建对象
* */

//包含抽象方法的类为抽象类
abstract class Father{
//没有方法体的方法称为抽象方法
public abstract void eat();
public abstract void sleep();
}

//创建A类继承于Father
class A extends Father{
//重写父类的方法
public void eat(){
System.out.println("喜欢吃.....");
}
public void sleep(){
System.out.println("喜欢睡.....");
}
}

public class AbstractDemo1 {
public static void main(String[] args) {
//创建对象
/*A f = new A();
f.eat();
f.sleep();*/
//创建多态
Father f = new A();//表示 father父类的变量指向A类
f.eat();
f.sleep();
}
}




接口
我们使用interface关键字定义接口,一般使用接口声明 方法常量,接口中的方法只能是声明,不能是具体的实现,这一点和抽象类是不一样的.接口是更高级别的抽象.其接口定义格式:
[修饰符] interface 接口名 [extends 父接口1,父接口2...]{
//成员常量:public static final
//抽象方法:public abstract
//方法只用方法声明,而且是公共的
public void 方法名称();
}
类要实现接口,只需要使用implement关键字,实现类必须要实现接口中的所有方法
public class 需要实现的类名 implement 接口{
//实现接口的方法
}

> 接口中的成员修饰符是固定的,写不写都有
成员常量:public static final
抽象方法:public abstract
接口中的成员都是pub离线修饰的

> 接口的出现将"多继承"通过另一种形式体现出来,即"多实现"


接口应用
1. 接口格式的练习
package com.oldboy_02;

/*
* public interface 接口名 [extends 接口1,接口2...]{
* 常量 public static final
* 抽象方法
* }
*
* 接口的使用:
* 接口中的常量:推荐使用接口名.访问常量
* 接口中的抽象方法:通过子类对象的方式实现
*
* 接口和抽象类的区别:
* 抽象类只能单继承,接口能多实现
*
* implement:实现
* 实现类 implement 接口
* */

//自定义接口A
interface InterA {
// 修饰成员变量
public static final int a = 10;
int b = 20; // 把public static final省略

// 抽象方法
public abstract void show1();

void show2(); // 把public static final省略
}

// 自定义接口B
interface InterB {
int c = 26;

void show3();
}

// 自定义类A,实现接口A和接口B,类A需要将接口A和B中的方法全部重写
class C implements InterA, InterB {
public void show1() {
System.out.println("显示1:老男孩教育");
}

public void show2() {
System.out.println("显示2:大数据开发");
}

public void show3() {
System.out.println("显示3:Python全栈开发");
}
}

public class InterfaceDemo1 {
public static void main(String[] args) {
// 创建对象
C c = new C();

// 使用对象名.变量表示
System.out.println("a的值为:" + c.a + "\r\nb的值为:" + c.b);
System.out.println("a的值为:" + c.c);
c.show1();
c.show2();

System.out.println("=======================");
// 使用接口名.变量表示
System.out.println("a的值为:" + InterA.a + "\r\nb的值为:" + InterA.b);
System.out.println("c的值为:" + InterB.c);
c.show3();
}
}

2. 接口扩展类功能
package com.oldboy_02;

/*
* 接口扩展类的功能
* */

//自定义类Dog
class Dog{
public void run(){
System.out.println("run: 这条够是哈士奇");
}
}

interface Jump{
public abstract void jump();
}

//自定义类JumpDog,继承于Dog,实现接口JumpDog
class JumpDog extends Dog implements Jump{
public void jump(){
System.out.println("Jump: 这只哈士奇喜欢跳");
}
}

public class InterfaceDemo2 {
public static void main(String[] args) {
//创建对象
JumpDog jd = new JumpDog();
jd.jump();
jd.run();
}
}

3.接口参数传递和返回值的练习
package com.oldboy_02;

/*
* 接口应用之:
* 1.作为参数传递
* 实际传递的是实现了此接口的子类的一个对象
* 2.作为返回值
* 实际返回的是实现了此接口的子类的一个对象
*
* */

//自定义接口
interface InterD {
public abstract void show();
}

// 接口的实现类
class AA implements InterD {
// 实现接口中的所有方法
public void show() {
System.out.println("Big Data");
}
}

class Test {
// 形式参数是接口类型,实际需要的是此接口的实现子类的一个对象
public void test(InterD a) {// 传递的是子类的实例对象
a.show();
}

// 返回值为接口类型,实际返回的是实现了此接口的子类的一个对象
public InterD getInterD() {
AA a = new AA();
return a;
//return new AA();// 匿名对象,这行代码等价于AA a = new AA(); return a;
}
}

// 自定义测试类
public class InterfaceDemo3 {
public static void main(String[] args) {
Test t = new Test();
// AA a = new AA();
// t.test(a);//将接口的实现类对象当成参数传递

// 返回值类型是接口,用对应的接口类型变量接住(属于多态知识)
InterD a = t.getInterD();
a.show();
}
}

接口的应用
定义一个接口非常简单,当然其实要设计一个好的接口并不是很简单,你必须要想好这个接口有什么常量和方法。但是技术却非常简单,示例代码如下:
// 定义方法的接口
public interface My interface {
// 定义程序使用的常量的接口,接口中只能有常量。
public static final double price = 1450.00;
public static final int counter = 5;
//接口中所有的方法都没有方法体。
public void add( int x, int y);
public void volume( int x, int y, int z);
}
实现接口也没有什么难度,代码如下:
//实现 接口
public class MyImple implements My interface {
@Override
public void add( int x, int y) {
}
@Override
public void volume( int x, int y, int z) {
}
}
一个类是可以实现多个接口,因为java是单继承的,这点接口可以弥补。我们可以再定义一个接口
public interface MyInterface2 {
public void countpp();
}
修改上面的实现类,要实现多个接口,可以使用逗号隔开,当然所有的接口的方法都要实现。
//实现 接口1,接口2
public class MyImple implements My interface ,MyInterface2{
@Override
public void add( int x, int y) {
}
@Override
public void volume( int x, int y, int z) {
}
@Override
public void countpp() {
}
}

接口与抽象的区别
1. 抽象类中可以有非抽象方法,即可以有方法体,但是接口中有方法实现是不行的.接口里只能有抽象方法,接口体现的是一种规范,抽象类体现的是模板是的设计.
2. 接口是抽象类的变体,在接口中,所有的方法都是抽象的,所有的变量也都是抽象的.接口只可以定义static final公共静态的成员变量.抽象类中的变量是普通变量.
3. 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象.
4. 抽象类要被子类继承,而接口是要被类使用implements实现.
5. 抽象类中的抽象方法必须全部被子类实现,如果子类不能全部实现父类的抽象方法,那么该子类智能是抽象类.同样,一个实现接口的时候,如不能全部实现接口方法 ,那么还累也只能为抽象类.
6. 抽象方法只能声明,不能实现,接口是设计的结果,抽象类是重构的结果
7. 如果一个类有抽象方法,那么这个类只能是抽象类
8. 抽象方法要被实现,所以不能是静态的,也不能是私有的.接口里的变量全部都是静态变量
9. 接口可继承接口,并可以多继承接口,但类只能单继承

1.抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别是最高的
2.抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量
3.抽象类主要用来抽象类别,接口主要用来抽象功能
4.抽象类中,且不包含任何实现,派生类必须覆盖他们(实现方法重写).接口中所有方法都必须是未实现的


多态(Ploymorphism)
多态是指同一个行为具有多个不同的表现形式或形态的能力.
多态就是同一个接口,使用不同的实例而执行不同操作.

多态存在的三个必要条件
1.继承
2.重写
3.父类引用指向子类对象
例如:
Father f = new Son();
当使用多态方式调用方法时,首先检查父类中是否有该方法,没有则会编译报错,有再去调用子类的同名方法.

多态应用
/*
多态:
父类(接口)类型的变量在调用方法的时候,会动态的去找真正指向的子类对象.并调用对应的方法.
多态实现的前提:
父子类(接口和实现类)
必须有方法的重写(方法的实现)
必须有父类对象指向子类实例
Person p{
eat(){A}
}
A extends Person{
eat(){ a}
}
B extends Person{
eat(){b}
}
B b = new B();
b.eat();
Person p = new Person();
p.eat();
Person p1 = new A();
p1.eat();
*/
//普遍类多态
class Father{
//成员变量没有多态性
int age = 20;
public void test(){
System.out.println("Father test()....");
}
//静态方法没有多态性
public static void method(){
System.out.println("Father static method()...");
}
}

class Son1 extends Father{
int age = 30;
public void test(){
System.out.println("Son1 test()....");
}
public static void method(){
System.out.println("Son1 static method()...");
}
}


class Son2 extends Father{
public void test(){
System.out.println("Son2 test()....");
}
public static void method(){
System.out.println("Son2 static method()...");
}
}

//抽象类多态
abstract class A{
public abstract void show();
}

class B extends A{
public void show(){
System.out.println("B show()...");
}
}

class C extends A{
public void show(){
System.out.println("C show()...");
}
}

//接口多态
interface InterA{
public static final int i = 10;
public abstract void fun();
}

class InterAImpl implements InterA{
public void fun(){
System.out.println("InterAimpl fun...");
}
}

class InterAImpl2 implements InterA{
//
public int n = 20;
//实现类特有方法
public void fun2(){
System.out.println("InterAimpl2 fun2...");
}
public void fun(){
System.out.println("InterAimpl2 fun...");
}
}

public class PolymorphismDemo{
public static void test(InterA a){//这里实际上是接口多态 InterA a = new InterAImpl();
a.fun();
}
public static void main(String[] args){
//没有多态性
/*
Father f = new Father();
f.test();
*/
//普通类之间的多态(父类不包含抽象方法)
Father f = new Son1();
// System.out.println(f.age);//
f.method();
// f.test();
/*
Father f2 = new Son2();
f2.test();
*/
//抽象类多态
/*
A a = new B();
a.show();
A a2 = new C();
a2.show();
*/
//接口多态
//多态中,父类类型的变量无法调用子类特有的方法或访问子类特有的成员变量
/*
InterA a = new InterAImpl();
System.out.println(a.i);
// System.out.println(a.n);
// a.fun();
InterA b = new InterAImpl2();
// b.fun2();
*/
}
}



















猜你喜欢

转载自blog.csdn.net/czz1141979570/article/details/79939616