1.理解多态
知道了向上转型,动态绑定,方法重写之后。我们就可以使用多态的形式来设计程序。这样就可以只关注父类的代码,就能够同时兼容各种子类的情况【一个引用, 能表现出多种不同形态】
class Shape {
protected String name;
public void draw() {
}
public Shape(String name) {
System.out.println("Shape::name-->");
}
}
class Cycle extends Shape {
public Cycle(String name) {
super(name);
}
@Override
public void draw() {
System.out.println("画一个圆");
}
}
class React extends Shape {
public React(String name) {
super(name);
}
@Override
public void draw() {
System.out.println("画一个矩形");
}
}
class Triangle extends Shape {
public Triangle(String name) {
super(name);
}
@Override
public void draw() {
System.out.println("画一个三角形");
}
}
public class TestDemo2 {
/**
* 什么是多态
* 1.父类引用 引用子类对象
* 2.父类和子类有同名的覆盖方法
* 3.通过父类引用代用这个重写的方法的时候
*
* @param shape
*/
public static void drawMap(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
Shape shape1 = new Cycle("山地自行车");
Shape shape2 = new React("矩形方阵");
Shape shape3 = new Triangle("红色三角");
/*shape1.draw();
shape2.draw();*/
/*
多态的单个调用
*/
drawMap(shape1);
drawMap(shape2);
drawMap(shape3);
String[] shapes = {
"Cycle", "React", "Triangle", "Cycle"};
/*
for循环+if判断实现打印
*/
for (String v : shapes) {
if (v.equals("Cycle")) {
new Cycle("山地自行车").draw();
}else if (v.equals("React")) {
new React("矩形").draw();
}else if (v.equals("Flower")) {
new Triangle("三角形").draw();
}
}
/*
通过数组+多态:实现循环打印
*/
Shape[] shapes1 = {
new Cycle("山地行车"), new React("矩形") , new Triangle("三角形")};
for (Shape v : shapes1) {
v.draw();
}
}
当类的调用者在编写 drawMap 这个方法的时候, 参数类型为 Shape (父类), 此时在该方法内部并不知道,
也不关注当前的 shape 引用指向的是哪个类型(哪个子类)的实例. 此时 shape 这个引用调用 draw 方法
可能会有多种不同的表现(和 shape 对应的实例相关), 这种行为就称为 多态.
2.理解抽象类
抽象类
- 抽象方法:一个方法如果被abstract修饰,那么这个方法就是抽象方法。抽象方法可以没有具体的实现
2.包含抽象方法的类是抽象类–>类加上abstract修饰 - 注意:
1.抽象类不可以被实例化,不能Shape shape = new Shape();
2. 类内的数据成员和普通类没有区别
3. 抽象类主要用来被继承
4. 如果一个类继承了这个抽象类,那么这个类必须重写抽象类当中的抽象方法
5. 当抽象类A 继承 抽象类Cycle 那么A可以不重写Cycle中的方法,但是一旦A要是再被继承,那么一定要重写这个抽象方法
6. 抽象类/抽象方法 一定不能是被final修饰的
bstract class Shape {
private int a;
// final private int b;
public void func(){
}
public abstract void draw();、// 不带{}说明是抽象方法,便于子类方法重写
}
/*abstract class Cycle extends Shape {}
class A extends Cycle{
public void draw(){};
}*/
class Cycle extends Shape {
@Override
public void draw() {
}
}
class React extends Shape {
@Override
public void draw() {
System.out.println("画一个矩形");
}
}
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("画一个三角形");
}
}
public class TestDemo {
public static void drawMap(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
Shape shape1 = new Cycle();
Shape shape2 = new React();
drawMap(shape1);
drawMap(shape2);
}
3.接口
接口(Interface)
- 接口当中的方法,都是抽象方法
- 其实可以有具体实现的方法[,这个方法是被default修饰的JDK1.8加入的]
- 接口当中定义的成员变量默认是 常量 一定要赋值,否则会报错
- 接口当中的 成员变量默认是: public static final; 成员方法默认是: public abstract
- 接口是不可以被实例化,
- 接口和类的关系
- 接口的出现是为了解决Java单继承问题
- 只要这个类实现了该接口,那么就可以实现向上转型
interface Shape {
public static final int a = 10;
public abstract void draw();
default public void func1() {
System.out.println("default接口方法");
}
}
interface A {
}
class Circle implements Shape, A {
@Override
public void draw() {
System.out.println("画⚪");
}
}
class React implements Shape {
@Override
public void draw() {
System.out.println("画♦");
}
}
public class TestInterface {
public static void drawMap(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
// Shape shape = new Shape();// 接口是不可以被实例化,
Shape shape1 = new Circle();
Shape shape2 = new React();
drawMap(shape1);
drawMap(shape2);
}
4.接口
- 实例运用1[普普通通的阿猫阿狗创建]
```java
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}
interface IFlying {
void fly();
}
interface IRunning {
void run();
}
interface ISwimming {
void swim();
}
/*
1.一个类可以继承一个普通类/抽象类,并且可以同时实现多个接口
先 extend 再 implements
*/
class Cat extends Animal implements IRunning {
public Cat(String name) {
super(name);
}
public void run() {
System.out.println(this.name + "正在用四条腿跑");
}
}
class Fish extends Animal implements ISwimming {
public Fish(String name) {
super(name);
}
public void swim() {
System.out.println(this.name + "正在尾巴游");
}
}
class Frog extends Animal implements IRunning, ISwimming{
public Frog(String name) {
super(name);
}
public void run() {
System.out.println(this.name + "正在跑");
}
public void swim() {
System.out.println(this.name + "正在游");
}
}
class Robot implements IRunning{
@Override
public void run() {
System.out.println("我是机器人,正在跑");
}
}
public class TestMoreExtends {
public static void walk(IRunning running) {
System.out.println("我带着伙伴去散步");
running.run();
}
public static void main(String[] args) {
IRunning iRunning = new Robot();
iRunning.run();
walk(iRunning);
IRunning iRunning1 = new Frog("青青");
walk(iRunning1);
ISwimming iSwimming = new Frog("青青");
}
- 实力运用2[创建一个学生,并且按照年龄排序]
看Comparable源码,自己要构建一个排序方法类似于C语言中的Qsort排序
/**
* 一般情况下,自定义类型进行比较 需要是 可比较 的
* Comparable 和 Comparator
*/
import java.util.Arrays;
class Student implements Comparable<Student> {
public String name;
public int age;
public int score;
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
// 再Student中implements实现泛型Comparable。然后wind[alt+enter]选择implement mehod实现方法
@Override
public int compareTo(Student o) {
if (this.age > o.age) {
//以年龄来比较
return 1;
} else if (this.age < o.age) {
return -1;
} else {
return 0;
}
// return 0;
}
}
public class TestDemo {
public static void main(String[] args) {
Student student1 = new Student("bit", 18, 79);
Student student2 = new Student("gaobo", 29, 70);
Student student3 = new Student("shasha", 3, 99);
if (student1.compareTo(student2) > 0) {
System.out.println("student1的年龄 > student2");
} else if (student1.compareTo(student2) < 0) {
System.out.println("student1的年龄 < student2");
} else {
System.out.println("student1的年龄 == student2");
}
Student[] students = new Student[3];
students[0] = student1;
students[1] = student2;
students[2] = student3;
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
public static void main1(String[] args) {
int[] array = {
12, 3, 89, 43, 56};
Arrays.sort(array);
System.out.println(Arrays.toString(array));
int a = 10, b = 20;
}