文章目录
一、 封装
1、概念
将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节
,仅对外公开接口来和对象进行交互。
举个例子:平时生活中用到的电脑,用户看不见内部实现的细节,只留一下接口给用户使用。
class Student{
private String name;
private int age;
}
这里定义了一个学生类,类中的两个成员变量,用private(访问限定修饰符)修饰,让该成员方法只能在当前类中使用,不能在当前类外使用。
2、优点
- 安全:隐藏数据,防止被随意修改。
- 可控:通过方法操作数据,可以加入验证逻辑。
- 易维护:内部修改不影响外部调用。
- 简化使用:使用者无需了解内部复杂实现。
总结:封装让代码更安全、更灵活、更容易维护。
二、继承
1、概念
继承(inheritance)机制:是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加新功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程。继承主要解决的问题是:共性的抽取,实现代码复用
。
举个例子
Animal 类
public class Animal {
public String name;
public int age;
}
Cat类继承Animal类
public class Cat extends Animal{
public void mew(){
System.out.println(name+"喵喵....");
}
}
Dog类继承Animal类
public class Dog extends Animal{
public void bark(){
System.out.println(name+"汪汪汪......");
}
}
Test类
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "小黄";
dog.age = 3;
dog.bark();
Cat cat = new Cat();
cat.name = "小花";
cat.age = 4;
cat.mew();
}
}
上面的Dog,Cat类==(子类/派生类)==继承了父类Animal类(父类/基类/超类),对它们的共性:名字和年龄进行抽取,实现了代码的复用。
建议的写法:一个java文件一个类
2、父类成员访问
2.1 子类中访问父类的成员变量
Base父类
public class Base {
public int a = 1;
public int b = 2;
}
Derived子类
public class Derived extends Base{
public int c = 3;
public int a = 100;
public void func(){
System.out.println("a="+this.a);
System.out.println("b="+this.b);
System.out.println("c="+this.c);
}
}
Test测试类
public class Test {
public static void main(String[] args) {
Derived derived = new Derived();
derived.func();
}
}
此时父类和子类有同名的成员变量 a,优先访问自己的。遵循就近原则,自己有优先自己的,如果没有则从父类中找。
打印结果
2.2 super关键字:在子类方法中访问父类的成员
Derived子类
public class Derived extends Base{
public int c = 3;
public int a = 100;
public void func(){
//在子类方法中访问父类的成员
System.out.println("a="+super.a);
System.out.println("b="+this.b);
System.out.println("c="+this.c);
}
}
打印结果
此时使用Java中的super关键字,成员变量a的值打印的就是父类中的1。
2.3 总结
在子类方法中 或者 通过子类对象访问成员时:
1.如果访问的成员变量子类中有,优先访问自己的成员变量。
2.如果访问的成员变量子类中无,则访问父类继承下来的,如果父类也没有定义,则编译报错。
3.如果访问的成员变量与父类中成员变量同名,则优先访问自己的。
4.成员方法也遵循上面原则。
super关键字的注意事项:
1.只能在非静态方法中使用。
2. 在子类方法中,访问父类的成员变量和方法。
3、继承的优点
-
代码复用
子类可以直接继承父类的属性和方法,无需重复编写相同的代码,提高了开发效率。 -
提高扩展性
子类可以在继承的基础上,添加新的属性和方法,或者重写父类的方法,以适应新的需求,系统易于扩展。 -
便于维护
当需要修改公共特性时,只需在父类中修改一次,所有子类都会自动继承这个修改,降低了维护成本和出错风险。 -
模拟现实世界关系
继承能够很自然地描述现实世界中“是一种(is-a)”的关系(如:猫是一种动物),使模型更符合逻辑,易于理解。
总结
继承通过建立类之间的层次关系,实现了代码的高效复用、轻松扩展和集中维护。
三、多态
1、概念
通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
2、多态实现的条件
在java中要实现多态,必须要满足以下条件,缺一不可。
- 必须在继承体系下
- 子类必须要对父类中方法进行重写
- 通过父类的引用调用重写的方法
2.1向上转型(补充)
概念:实际就是创建一个子类对象,将其当成父类对象来使用。
向上转型有三种
方式:直接赋值,方法的传参,方法返回。
向上转型的优点
:让代码实现更简单灵活。
向上转型的缺陷
:不能调用到子类特有的方法。
2.1.1 直接赋值
Animal父类
public class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("正在吃饭.....");
}
Dog子类
public class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void bark(){
System.out.println(this.name+"正在汪汪叫....");
}
}
Test测试类
public class Test {
public static void main(String[] args) {
Animal animal = new Animal("旺财",7); //向上转型 父类引用 引用了子类对象
}
}
2.1.2 方法的传参
Test测试类
public class Test {
public static void func(Animal animal){
}
public static void main(String[] args) {
Dog dog = new Dog("小黄",4);
func(dog);
}
}
2.1.2 方法返回
Test测试类
public class Test {
public static Animal func(){
Dog dog = new Dog("小黄",4);
return dog;
}
public static void main(String[] args) {
Animal animal = func();
}
}
2.2动态绑定(理解多态的基础)
前提:一定要在继承的情况下
。
1.父类引用 引用了子类对象。
2.通过父类的引用调用了父类和子类重写的那个方法。
Animal父类
public class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("正在吃饭.....");
}
}
Dog子类
public class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void bark(){
System.out.println(this.name+"正在汪汪叫....");
}
@Override
public void eat(){
System.out.println("狗狗正在吃狗粮.....");
}
}
Test测试类
public class Test {
public static Animal func(){
Dog dog = new Dog("小黄",4);
return dog;
}
public static void main(String[] args) {
Animal animal = func();
animal.eat();
}
}
打印结果
这里我们发现打印的结果是Dog子类eat()方法中的“狗狗正在吃狗粮…” ,是因为这里发生了动态绑定。编译的时候调用的确实是父类的eat()方法,当代码运行的时候,通过父类的引用调用了父类和子类重写的eat()方法,结果
实际调用了Dog子类eat()
方法。
2、多态代码例子讲解
Animal父类
public class Animal {
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(){
System.out.println("正在吃饭.....");
}
}
Dog子类
public class Dog extends Animal{
public Dog(String name, int age) {
super(name, age);
}
public void bark(){
System.out.println(this.name+"正在汪汪叫....");
}
@Override
public void eat(){
System.out.println("狗狗正在吃狗粮.....");
}
}
Bird子类
public class Bird extends Animal{
public Bird(String name, int age) {
super(name, age);
}
public void fly(){
System.out.println(this.name+"正在飞....");
}
@Override
public void eat(){
System.out.println("鸟儿正在吃虫子.....");
}
}
Test测试类
public class Test {
public static void func(Animal animal){
animal.eat();
}
public static void main(String[] args) {
Dog dog = new Dog("旺财",3);
func(dog);
System.out.println("=================");
Bird bird = new Bird("小鸟",2);
func(bird);
}
}
打印结果
这里我们写了两个子类 Dog 和Bird,两个类都重写了Animal父类的eat()方法。在Test类中animal引用的对象不一样
,但是调用的是同一个方法
(eat()方法),此时表现出的现象不一样
,这种思想就叫做多态
。
3、多态的优缺点
3.1优点
- 能够降低代码的 “圈复杂度”(一种描述一段代码复杂程度的方式), 避免使用大量的 if - else。
- 可扩展能力更强。
3.2缺点
1.代码的运行效率降低。
2.属性没有多态性,当父类和子类都有同名属性的时候,通过父类引用,只能引用父类自己的成员属性。
3.构造方法没有多态性。