2、抽象类和接口 本季主要知识点: 抽象类和接口的实际应用 1、子类对象可以为父类对象实例化,之后调用的方法都是子类中已经被覆写过的方法。
2、就可以利用此特性,观察抽象类的使用,因为在抽象类中有很多的抽象方法。 抽象类 abstract class A
{
public abstract void fun();
};
class B extends A
{
public void fun()
{
System.out.println("B ==> Hello World");
}
};
class C extends A
{
public void fun()
{
System.out.println("C ==> Hello World");
}
};
public class Demo01
{
public static void main(String args[])
{
A a = new B();
a.fun();
}
}; abstract class A
{
public abstract void fun();
};
class B extends A
{
public void fun()
{
System.out.println("B ==> Hello World");
}
};
class C extends A
{
public void fun()
{
System.out.println("C ==> Hello World");
}
};
public class Demo01
{
public static void main(String args[])
{
A a = new C();
a.fun();
}
}; 抽象类是可以实例化的,通过对象的多态性来实例化 抽象类的主要作用是什么呢?抽象类就是类似于一个模板操作 ==>JAVA WEB Servlet程序,提供的就是一个模板。 把上面的实际的例子变为程序 abstract class Err
{
public void printInfo()
{
System.out.println("姓名:"+this.getName());
System.out.println("班级:"+this.getCls());
System.out.println("事由:"+this.getCau());
}
//得到姓名,由具体的子类去做
public abstract String getName();
//得到班级,由具体的子类去做
public abstract String getCls();
//得到事由
public abstract String getCau();
}
class ZhangSan extends Err
{
public String getName()
{
return "张三";
}
public String getCls()
{
return "小五班";
}
public String getCau()
{
return "因为上课吃东西,所以被老师抓住了,所以要填写违纪卡。 ";
}
}
class LiSi extends Err
{
public String getName()
{
return "李四";
}
public String getCls()
{
return "大五班";
}
public String getCau()
{
return "因为上课睡觉,所以被老师抓住了,所以要填写违纪卡。 ";
}
}
public class Demo02
{
public static void main(String args[])
{
Err e = new ZhangSan();
e.printInfo();
}
} 我们改成李四看看效果哈~ abstract class Err
{
public void printInfo()
{
System.out.println("姓名:"+this.getName());
System.out.println("班级:"+this.getCls());
System.out.println("事由:"+this.getCau());
}
//得到姓名,由具体的子类去做
public abstract String getName();
//得到班级,由具体的子类去做
public abstract String getCls();
//得到事由
public abstract String getCau();
}
class ZhangSan extends Err
{
public String getName()
{
return "张三";
}
public String getCls()
{
return "小五班";
}
public String getCau()
{
return "因为上课吃东西,所以被老师抓住了,所以要填写违纪卡。 ";
}
}
class LiSi extends Err
{
public String getName()
{
return "李四";
}
public String getCls()
{
return "大五班";
}
public String getCau()
{
return "因为上课睡觉,所以被老师抓住了,所以要填写违纪卡。 ";
}
}
public class Demo02
{
public static void main(String args[])
{
Err e = new LiSi();
e.printInfo();
}
} 调用模板成功了哈~ (模板设计)场景:
假设Person分为Worker和Student,工人的属性包括:姓名、年龄、工资,学生的属性包括:姓名、年龄、成绩,那么现在人都可以说话,但是工人和学生说的话肯定不一样。此时,肯定人中的说话方法是固定的,肯定是一个普通方法,只是说话的内容不一样。 abstract class Person
{
private String name;
private int age;
public Person(String name,int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return this.name;
}
public int getAge()
{
return this.age;
}
public void talk()
{
//这是要说,内容都在此方法中
System.out.println(this.getContent());
}
public abstract String getContent();
}
class Student extends Person
{
private float score;
public Student(String name,int age,float score)
{
super(name,age);
this.score = score;
}
public String getContent()
{
return "学生说 --> 姓名="+super.getName()
+",年龄="+super.getAge()
+",成绩="+this.score;
}
}
class Worker extends Person
{
private float salary;
public Worker(String name,int age,float salary)
{
super(name,age);
this.salary = salary;
}
public String getContent()
{
return "工人说 --> 姓名="+super.getName()
+",年龄="+super.getAge()
+",工资="+this.salary;
}
}
public class Demo03
{
public static void main(String args[])
{
Person p1 = new Student("张三",20,90.0f);
Person p2 = new Worker("李四",30,900.0f);
p1.talk();
p2.talk();
}
} 接口的实际应用 分布式代码中最重要的就是要规定好操作的接口。接口就是定义了一个标准,只要按照此标准代码都可以正常使用。 interface A
{
public String getInfo();
}
class B implements A
{
public String getInfo()
{
return "B --> Hello World";
}
}
class C implements A
{
public String getInfo()
{
return "C --> Hello World";
}
}
public class Demo04
{
public static void main(String args[])
{
A a = new B();
System.out.println(a.getInfo());
}
} 证明接口对象可以实例化,通过对象多态性进行向上转型,接口是可以实例化的。 我们改成C看看效果 interface A
{
public String getInfo();
}
class B implements A
{
public String getInfo()
{
return "B --> Hello World";
}
}
class C implements A
{
public String getInfo()
{
return "C --> Hello World";
}
}
public class Demo04
{
public static void main(String args[])
{
A a = new C();
System.out.println(a.getInfo());
}
} 我们发现都可以利用对象多态性完成操作 接口是一个标准。
USB接口 --> 只要是实现了USB接口的设备就都可以向USB接口上插。
举例:
假设现在设计一个USB接口,里面只有开始工作和停止工作的操作。主板上有USB接口,表示可以插入任意的USB设备。 interface USB
{
//表示开始工作
public void start();
//表示停止工作
public void stop();
}
class MainBoard
{
//只要是USB设备就可以插
public static void plugIn(USB usb)
{
usb.start();
usb.stop();
}
}
class MP3 implements USB
{
public void start()
{
System.out.println("MP3开始工作");
}
public void stop()
{
System.out.println("MP3停止工作");
}
}
class Print implements USB
{
public void start()
{
System.out.println("打印机开始工作");
}
public void stop()
{
System.out.println("打印机停止工作");
}
}
public class Demo05
{
public static void main(String args[])
{
USB u = new MP3();
MainBoard.plugIn(u);
}
} 现在看下效果 如果是打印机呢? interface USB
{
//表示开始工作
public void start();
//表示停止工作
public void stop();
}
class MainBoard
{
//只要是USB设备就可以插
public static void plugIn(USB usb)
{
usb.start();
usb.stop();
}
}
class MP3 implements USB
{
public void start()
{
System.out.println("MP3开始工作");
}
public void stop()
{
System.out.println("MP3停止工作");
}
}
class Print implements USB
{
public void start()
{
System.out.println("打印机开始工作");
}
public void stop()
{
System.out.println("打印机停止工作");
}
}
public class Demo05
{
public static void main(String args[])
{
USB u = new Print();
MainBoard.plugIn(u);
}
} 这就是一个典型的操作,一切以接口标准进行操作。接口规定什么,其就可以完成什么样的工作哈~ 举例:
听我讲课,听我讲课,我说的是中文,你听的是中文,所以你能听懂,如果你再说话,你肯定也说中文,我听的也是中文。 接口在实际中可以作为一种标准,那么这种标准在使用的时候就可以让类之间进行解耦合操作。
接口的重要目的是解耦合: A --> B class A
{
public void fun(B b)
{
b.print();
}
}
class B
{
public void print()
{
System.out.println("Hello World!!!");
}
}
public class Demo06
{
public static void main(String args[])
{
new A().fun(new B());
}
} 此代码存在的问题:
如果现在B类的功能不能直接满足A类的要求了, 需要对B进行扩充或是把B类彻底替换成另外一个C类,那么此时要完成以下步骤:修改A类、增加C类,那么问有没有这样一种可能:修改功能的时候我可以不动类A呢?可以使用接口。 class A
{
public void fun(X x)
{
x.print();
}
}
interface X
{
public void print();
}
class B implements X
{
public void print()
{
System.out.println("Hello World!!!");
}
}
class C implements X
{
public void print()
{
System.out.println("Hello Java!!!");
}
}
public class Demo06
{
public static void main(String args[])
{
X x = new C();
new A().fun(x);
}
} 问题:
在实际的代码中main方法实际上应该是作为一个客户端出现的。
此时客户端与接口和其接口的子类是直接有关的。代码中肯定不能这样编写,因为会造成客户端(main)与具体的子类耦合。 JVM的工作原理: *.class -->JVM -->OS :程序可移植性高。 class A
{
public void fun(X x)
{
x.print();
}
}
interface X
{
public void print();
}
class B implements X
{
public void print()
{
System.out.println("Hello World!!!");
}
}
class C implements X
{
public void print()
{
System.out.println("Hello Java!!!");
}
}
//中间再加入一个过渡端
class Factory
{
public static X getInstance(String str)
{
X x = null;
if ("B".equals(str))
{
//认为操作的是B类
x = new B();
}
if ("C".equals(str))
{
x = new C();
}
return x;
}
}
public class Demo06
{
public static void main(String args[])
{
X x = Factory.getInstance("B");
new A().fun(x);
}
} 现在在客户端就看不到接口了 现在换成C标记 class A
{
public void fun(X x)
{
x.print();
}
}
interface X
{
public void print();
}
class B implements X
{
public void print()
{
System.out.println("Hello World!!!");
}
}
class C implements X
{
public void print()
{
System.out.println("Hello Java!!!");
}
}
//中间再加入一个过渡端
class Factory
{
public static X getInstance(String str)
{
X x = null;
if ("B".equals(str))
{
//认为操作的是B类
x = new B();
}
if ("C".equals(str))
{
x = new C();
}
return x;
}
}
public class Demo06
{
public static void main(String args[])
{
X x = Factory.getInstance("C");
new A().fun(x);
}
} 此时客户端并没有一个具体的子类出现。 class A
{
public void fun(X x)
{
x.print();
}
}
interface X
{
public void print();
}
class B implements X
{
public void print()
{
System.out.println("Hello World!!!");
}
}
class C implements X
{
public void print()
{
System.out.println("Hello Java!!!");
}
}
//中间再加入一个过渡端
class Factory
{
public static X getInstance(String str)
{
X x = null;
if ("B".equals(str))
{
//认为操作的是B类
x = new B();
}
if ("C".equals(str))
{
x = new C();
}
return x;
}
}
public class Demo06
{
public static void main(String args[])
{
if (args.length!=1)
{
System.out.println("程序参数错误,程序无法运行!");
System.exit(1);
}
X x = Factory.getInstance(args[0]);
new A().fun(x);
}
}
以后如果假设要增加新的子类的时候,只需要修改工厂类即可,其他地方不用做太大的修改,即:
某一个代码的修改不影响被调用处的代码就是好的设计。 上面的例子中执行java Demo06 D出现NullPointerException错误,我们可以这样修改,加个判断if(x!=null)。 class A
{
public void fun(X x)
{
if(x!=null)
x.print();
}
}
interface X
{
public void print();
}
class B implements X
{
public void print()
{
System.out.println("Hello World!!!");
}
}
class C implements X
{
public void print()
{
System.out.println("Hello Java!!!");
}
}
//中间再加入一个过渡端
class Factory
{
public static X getInstance(String str)
{
X x = null;
if ("B".equals(str))
{
//认为操作的是B类
x = new B();
}
if ("C".equals(str))
{
x = new C();
}
return x;
}
}
public class Demo06
{
public static void main(String args[])
{
if (args.length!=1)
{
System.out.println("程序参数错误,程序无法运行!");
System.exit(1);
}
X x = Factory.getInstance(args[0]);
new A().fun(x);
}
}
最早:接口直接去通过new 子类取得对象,那么这样造成一个接口与具体的子类直接耦合
现在:接口通过一个工厂类取得子类对象(根据传入的参数不同),此时接口与具体子类之间没有直接的耦合关系,所以使用接口可以解耦合。 此设计称为工厂设计模式:
接口 --> 工厂 --> 各个的子类对象 总结
1、重点阐述了抽象类和接口的使用
2、注意:自己简单总结一下抽象类和接口的不同
3、工厂设计 ############################################################
本文出自 “王乾De技术博客” 博客,谢绝转载!