面向对象(下)


一、继承

1.继承的含义:
把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系, 这多个类就具备了这些内容。这个关系叫继承。

2.Java中表示继承的格式:
1)用关键字extends表示
2)格式: class 子类名 extends 父类名 {}

3.继承的好处:
1)提高了代码的复用性
2)提高了代码的维护性
3)让类与类产生了一个关系,是多态的前提

4.继承的弊端:
1)让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。
原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
2)打破了封装性

5.Java中继承的特点
1)Java中类只支持单继承
2)Java中可以多层(重)继承(继承体系)

6.继承的注意事项:
A:子类不能继承父类的私有成员
B:子类不能继承父类的构造方法,但是可以通过super去访问
C:不要为了部分功能而去继承

7.什么时候使用继承呢?
1)继承体现的是:is a的关系。
2)采用假设法

8.Java继承中的成员关系
1)成员变量
A:子类的成员变量名称和父类中的成员变量名称不一样
B:子类的成员变量名称和父类中的成员变量名称一样,访问方式:
子类的方法访问变量的查找顺序:
在子类方法的局部范围找,有就使用。
在子类的成员范围找,有就使用。
在父类的成员范围找,有就使用。
找不到,就报错。
2)构造方法
A:子类的构造方法默认会去访问父类的无参构造方法, 为了子类访问父类数据的初始化
B:父类中如果没有无参构造方法解决办法:
子类通过super去明确调用带参构造
子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造
让父类提供无参构造
3)成员方法
A:子类的成员方法和父类中的成员方法名称不一样
B:子类的成员方法和父类中的成员方法名称一样, 通过子类对象访问一个方法的查找顺序:
在子类中找,有就使用
在父类中找,有就使用
找不到,就报错

9.猫狗案例的分析和实现

package com.itheima;

/*
 猫狗案例讲解

 先找到具体的事物,然后发现具体的事物有共性,才提取出一个父类。

 猫:
 成员变量:姓名,年龄,颜色
 构造方法:无参,带参
 成员方法:
 getXxx()/setXxx()
 eat()
 palyGame()
 狗:
 成员变量:姓名,年龄,颜色
 构造方法:无参,带参
 成员方法:
 getXxx()/setXxx()
 eat()
 lookDoor()

 共性:
 成员变量:姓名,年龄,颜色
 构造方法:无参,带参
 成员方法:
 getXxx()/setXxx()
 eat()

 把共性定义到一个类中,这个类的名字叫:动物。
 动物类:
 成员变量:姓名,年龄,颜色
 构造方法:无参,带参
 成员方法:
 getXxx()/setXxx()
 eat()

 猫:	
 构造方法:无参,带参
 成员方法:palyGame()
 狗:
 构造方法:无参,带参
 成员方法:lookDoor()
 */
//定义动物类
class Animal {
	// 姓名
	private String name;
	// 年龄
	private int age;
	// 颜色
	private String color;

	public Animal() {
	}

	public Animal(String name, int age, String color) {
		this.name = name;
		this.age = age;
		this.color = color;
	}

	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 String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

	public void eat() {
		System.out.println("不要睡了,该吃饭了");
	}
}

// 定义猫类
class Cat extends Animal {
	public Cat() {
	}

	public Cat(String name, int age, String color) {
		super(name, age, color);
	}

	public void playGame() {
		System.out.println("猫玩英雄联盟");
	}
}

// 定义狗类
class Dog extends Animal {
	public Dog() {
	}

	public Dog(String name, int age, String color) {
		super(name, age, color);
	}

	public void lookDoor() {
		System.out.println("狗看家");
	}
}

// 测试类
class ExtendsTest5 {
	public static void main(String[] args) {
		// 测试猫
		// 方式1
		Cat c1 = new Cat();
		c1.setName("Tom");
		c1.setAge(3);
		c1.setColor("白色");
		System.out.println("猫的名字是:" + c1.getName() + ";年龄是:" + c1.getAge()
				+ ";颜色是:" + c1.getColor());
		c1.eat();
		c1.playGame();
		System.out.println("---------------");
		// 方式2
		Cat c2 = new Cat("杰瑞", 5, "土豪金");
		System.out.println("猫的名字是:" + c2.getName() + ";年龄是:" + c2.getAge()
				+ ";颜色是:" + c2.getColor());
		c2.eat();
		c2.playGame();
		// 测试狗
		// 方式1
		Dog d1 = new Dog();
		d1.setName("John");
		d1.setAge(5);
		d1.setColor("黑色");
		System.out.println("狗的名字是:" + d1.getName() + ";年龄是:" + d1.getAge()
				+ ";颜色是:" + d1.getColor());
		d1.eat();
		d1.lookDoor();
		System.out.println("---------------");
		// 方式2
		Dog d2 = new Dog("Smith", 7, "黄");
		System.out.println("狗的名字是:" + d2.getName() + ";年龄是:" + d2.getAge()
				+ ";颜色是:" + d2.getColor());
		d2.eat();
		d2.lookDoor();
	}
}



二、多态


1.多态的描述:

同一个对象在不同时刻体现出来的不同状态。


2.多态的前提:

1)有继承或者实现关系。

2)有方法重写。

3)有父类或者父接口引用指向子类对象。


3.多态的分类:

1)具体类多态

class Fu {}

class Zi extends Fu {}

Fu f = new Zi();


2)抽象类多态

abstract class Fu {}

class Zi extends Fu {}

Fu f = new Zi();


3)接口多态

interface Fu {}

class Zi implements Fu {}

Fu f = new Zi();


4.多态中的成员访问特点

1)成员变量:编译看左边,运行看左边

2)构造方法:子类的构造都会默认访问父类构造

3)成员方法:编译看左边,运行看右边

4)静态方法:编译看左边,运行看左边


5.多态的好处与弊端:

1)好处:

A:提高代码的维护性(继承体现)

B:提高代码的扩展性(多态体现)

2)弊端:

父不能使用子的特有功能。现象:子可以当作父使用,父不能当作子使用。


6.多态中的转型

1)向上转型:从子到父

2)向下转型:从父到子


7.猫狗案例

/*
	猫狗案例
 */
class Animal {
	public void eat() {
		System.out.println("吃饭");
	}
}

class Dog extends Animal {
	public void eat() {
		System.out.println("狗吃肉");
	}

	public void lookDoor() {
		System.out.println("狗看门");
	}
}

class Cat extends Animal {
	public void eat() {
		System.out.println("猫吃鱼");
	}

	public void playGame() {
		System.out.println("猫捉迷藏");
	}
}

class DuoTaiTest {
	public static void main(String[] args) {
		// 定义为狗
		Animal a = new Dog();
		a.eat();
		System.out.println("--------------");
		// 还原成狗
		Dog d = (Dog) a;
		d.eat();
		d.lookDoor();
		System.out.println("--------------");
		// 变成猫
		a = new Cat();
		a.eat();
		System.out.println("--------------");
		// 还原成猫
		Cat c = (Cat) a;
		c.eat();
		c.playGame();
		System.out.println("--------------");

		// 演示错误的内容
		// Dog dd = new Animal();
		// Dog ddd = new Cat();
		// ClassCastException
		// Dog dd = (Dog)a;
	}
}


三、抽象类


1.为什么用抽象类

在定义方法声明一样,但是每个具体的对象在具体实现的时候内容不一样的共性方法的时,则不能给出具体的方法体。

而一个没有具体的方法体的方法是抽象的方法。在一个类中如果有抽象方法,该类必须定义为抽象类。


2.抽象类的特点

1)抽象类和抽象方法必须用关键字abstract修饰

2)抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类

3)抽象类不能实例化

4)抽象类的子类

A:是一个抽象类。

B:是一个具体类。这个类必须重写抽象类中的所有抽象方法。


3.抽象类的成员特点:

1)成员变量:有变量,有常量

2)构造方法:有构造方法

3)成员方法:有抽象,有非抽象


4.抽象类的几个小问题

1)抽象类有构造方法,不能实例化,那么构造方法有什么用?

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

2)一个类如果没有抽象方法,却定义为了抽象类,有什么用?

为了不让创建对象

3)abstract不能和哪些关键字共存

a:final 冲突

b:private 冲突

c:static 无意义


5.猫狗案例

/*
	猫狗案例
		具体事物:猫,狗
		共性:姓名,年龄,吃饭

	分析:从具体到抽象
		猫:
			成员变量:姓名,年龄
			构造方法:无参,带参
			成员方法:吃饭(猫吃鱼)
			
		狗:
			成员变量:姓名,年龄
			构造方法:无参,带参
			成员方法:吃饭(狗吃肉)
			
		因为有共性的内容,所以就提取了一个父类。动物。
		但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的,
		而方法是抽象的类,类就必须定义为抽象类。
		
		抽象动物类:
			成员变量:姓名,年龄
			构造方法:无参,带参
			成员方法:吃饭();
	
	实现:从抽象到具体
		动物类:
			成员变量:姓名,年龄
			构造方法:无参,带参
			成员方法:吃饭();
			
		狗类:
			继承自动物类
			重写吃饭();
			
		猫类:
			继承自动物类
			重写吃饭();
 */
//定义抽象的动物类
abstract class Animal {
	// 姓名
	private String name;
	// 年龄
	private int age;

	public Animal() {
	}

	public Animal(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 abstract void eat();
}

// 定义具体的狗类
class Dog extends Animal {
	public Dog() {
	}

	public Dog(String name, int age) {
		super(name, age);
	}

	public void eat() {
		System.out.println("狗吃肉");
	}
}

// 定义具体的猫类
class Cat extends Animal {
	public Cat() {
	}

	public Cat(String name, int age) {
		super(name, age);
	}

	public void eat() {
		System.out.println("猫吃鱼");
	}
}

// 测试类
class AbstractTest {
	public static void main(String[] args) {
		// 测试狗类
		// 具体类用法
		// 方式1:
		Dog d = new Dog();
		d.setName("旺财");
		d.setAge(3);
		System.out.println(d.getName() + "---" + d.getAge());
		d.eat();
		// 方式2:
		Dog d2 = new Dog("旺财", 3);
		System.out.println(d2.getName() + "---" + d2.getAge());
		d2.eat();
		System.out.println("---------------------------");

		Animal a = new Dog();
		a.setName("旺财");
		a.setAge(3);
		System.out.println(a.getName() + "---" + a.getAge());
		a.eat();

		Animal a2 = new Dog("旺财", 3);
		System.out.println(a2.getName() + "---" + a2.getAge());
		a2.eat();

		// 测试猫类
		// 具体类用法
		// 方式1:
		Cat c = new Cat();
		c.setName("喵喵");
		c.setAge(4);
		System.out.println(c.getName() + "---" + c.getAge());
		c.eat();
		// 方式2:
		Cat c2 = new Cat("喵喵", 4);
		System.out.println(c2.getName() + "---" + c2.getAge());
		c2.eat();
		System.out.println("---------------------------");

		Animal b = new Cat();
		b.setName("喵喵");
		b.setAge(4);
		System.out.println(b.getName() + "---" + b.getAge());
		b.eat();

		Animal b2 = new Cat("喵喵", 4);
		System.out.println(b2.getName() + "---" + b2.getAge());
		b2.eat();
	}
}


四、接口


1.接口存在的意义

像猫钻火圈,狗跳高等功能,不是动物本身就具备的,是在后面的培养中训练出来的,这种额外的功能,java提供了接口表示。


2.接口的特点:

1)接口用关键字interface修饰:interface 接口名 {}

2)类实现接口用implements修饰:class 类名 implements 接口名 {}

3)接口不能实例化

4)接口的实现类

A:是一个抽象类。

B:是一个具体类,这个类必须重写接口中的所有抽象方法。


3.接口的成员特点:

1)成员变量,只能是常量,默认修饰符:public static final

2)没有构造方法

3)成员方法,只能是抽象的,默认修饰符:public abstract


4.类与接口之间的关系:

1)类与类:继承关系,只能单继承,可以多层继承

2)类与接口:实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时,实现多个接口

3)接口与接口:继承关系,可以单继承,也可以多继承


5.抽象类和接口的区别:

1)成员区别

抽象类:可以是常量也可以是变量

接口:只能是常量

2)关系区别:

类与类:继承

类与接口:实现关系,可以单实现,也可以多实现。

接口与接口:继承关系,可以单继承,也可以多继承

3)设计理念不同

抽象类:is a,抽象类中定义的是共性功能。

接口:like a,接口中定义的是扩展功能。


6.猫狗案例

/*
	猫狗案例,加入跳高的额外功能
	分析:从具体到抽象
		猫:
			姓名,年龄
			吃饭,睡觉
		狗:
			姓名,年龄
			吃饭,睡觉
			
		由于有共性功能,所以,我们抽取出一个父类:
		动物:
			姓名,年龄
			吃饭();
			睡觉(){}
			
		猫:继承自动物
		狗:继承自动物
		
		跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口
		接口:
			跳高
			
		部分猫:实现跳高
		部分狗:实现跳高
	实现;
		从抽象到具体
		
	使用:
		使用具体类
 */
//定义跳高接口
interface Jumpping {
	// 跳高功能
	public abstract void jump();
}

// 定义抽象类
abstract class Animal {
	// 姓名
	private String name;
	// 年龄
	private int age;

	public Animal() {
	}

	public Animal(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 abstract void eat();

	// 睡觉(){}
	public void sleep() {
		System.out.println("睡觉觉了");
	}
}

// 具体猫类
class Cat extends Animal {
	public Cat() {
	}

	public Cat(String name, int age) {
		super(name, age);
	}

	public void eat() {
		System.out.println("猫吃鱼");
	}
}

// 具体狗类
class Dog extends Animal {
	public Dog() {
	}

	public Dog(String name, int age) {
		super(name, age);
	}

	public void eat() {
		System.out.println("狗吃肉");
	}
}

// 有跳高功能的猫
class JumpCat extends Cat implements Jumpping {
	public JumpCat() {
	}

	public JumpCat(String name, int age) {
		super(name, age);
	}

	public void jump() {
		System.out.println("跳高猫");
	}
}

// 有跳高功能的狗
class JumpDog extends Dog implements Jumpping {
	public JumpDog() {
	}

	public JumpDog(String name, int age) {
		super(name, age);
	}

	public void jump() {
		System.out.println("跳高狗");
	}
}

class InterfaceTest {
	public static void main(String[] args) {
		// 定义跳高猫并测试
		JumpCat jc = new JumpCat();
		jc.setName("哆啦A梦");
		jc.setAge(3);
		System.out.println(jc.getName() + "---" + jc.getAge());
		jc.eat();
		jc.sleep();
		jc.jump();
		System.out.println("-----------------");

		JumpCat jc2 = new JumpCat("加菲猫", 2);
		System.out.println(jc2.getName() + "---" + jc2.getAge());
		jc2.eat();
		jc2.sleep();
		jc2.jump();
	}
}


五、内部类


1.内部类的定义:

把类定义在另一个类的内部,该类就被称为内部类。例如:把类B定义在类A中,类B就被称为内部类。


2.内部类的访问规则

1)可以直接访问外部类的成员,包括私有

2)外部类要想访问内部类成员,必须创建对象


3.内部类的分类

1)成员内部类

A:private 为了数据的安全性

B:static 为了访问的方便性

成员内部类不是静态的:

外部类名.内部类名  对象名 = new 外部类名.new 内部类名();

成员内部类是静态的:

外部类名.内部类名  对象名 = new 外部类名.内部类名();

2)局部内部类

局部内部类访问局部变量必须加final修饰。因为局部变量使用完毕就消失,而堆内存的数据并不会立即消失。所以,堆内存还是用该变量,而改变量已经没有了。

为了让该值还存在,就加final修饰。通过反编译工具我们看到了,加入final后,堆内存直接存储的是值,而不是变量名。


4.匿名内部类

1)是局部内部类的简化形式

2)前提存在一个类或者接口

3)格式:

new 类名或者接口名() {
	重写方法;
}

4)本质:其实是继承该类或者实现接口的子类匿名对象


5.匿名内部类在开发中的使用

在开发的时候,会看到抽象类,或者接口作为参数。而这个时候,我们知道实际需要的是一个子类对象。

如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。

interface Person {
	public abstract void study();
}

class PersonDemo {
	public void method(Person p) {
		p.study();
	}
}

class PersonTest {
	public static void main(String[] args) {
		PersonDemo pd = new PersonDemo();
		pd.method(new Person() {
			public void study() {
				System.out.println("好好学习,天天向上");
			}
		});
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值