前言
Java面向对象编程作为一种编程思想,有三大特性,封装,继承,多态。对于一个类而言, 如何封装 呢?继承是父类和子类的关系, 继承关系如何实现的呢?父类和子类继承时的方法体是怎么样的关系呢?多态是多个类之间的关系,类有不同的行为和属性,其他类也有这样的方法和属性,就实现了多态的关系,不同类的多态实现是怎么样实现的呢?
一、构造函数
构造函数是面向对象中的一员,构造函数可以叫做构造器,它的函数名与类名相同,不用定义返回值类型,也没有具体的返回值。构造函数是在构建创造时对象时调用函数,作用是可以给对象进行初始化,创建对象都必须要通过构造函数初始化。一个类中如果没有定义过构造函数,那么该类会有一个默认的空参数构造函数。如果在类中定义了指定的构造函数,那么该类中的默认构造函数就没有了。
在描述事物时,该事物已存在就具备的一些内容,这些内容都定义在构造函数中时可以定义构造函数。一个类当中可以有多个是可以给不同的对象进行不同的初始化,多个构造函数在一个类中出现他们的存在的形式就是叫做重载。重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同 也可以不同。被重载的方法必须形参列表不一样,参数个数或类型不一样,重载方法能够在同一个类中或者在一个子类中被重载
一般函数和构造函数的区别:构造函数在创建对象时,就会调用与之对应的构造函数,对象进行初始化。对象创建时,构造函数会调用也只调用一次。因为构造函数命名时跟类名一样,首字母要大写;而一般函数对象创建后,需要函数功能时才调用。对象创建后,一般函数可以被调用多次,一般函数的命名首字母是小写的
二、面向对象的三大特征
1.封装
- 什么是封装?
把客观事物封装成抽象的类,并且把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。也 就 是 说抽象数据类型对数据信息以及对数据的操作进行打包,将其变成一个不可分割 的实体,在这个实体内部,我们对数据进行隐藏和保密,只留下一些接口供外部调用。
简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分。
封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。
为什么需要封装
为什么需要封装
隐藏一个类中不需要对外提供的实现细节;
属性的封装:使用者只能通过事先定制好的方法来访问数据,可以方便地加入逻辑控制,限制对属性的 不合理操作;
方法的封装:使用者按照既定的方式调用方法,不必关心方法的内部实现,便于使用; 便于修改,增强 代码的可维护性;
-如何封装
利用权限修饰符来描述方法体或属性。private修饰的属性或方法为该类所特有,在任何其他类中都不能直接访问;default修饰的属性或方法具有包访问特性,同一个包中的其他类可以访问;protected修饰的属性或方法在同一个中的其他类可以访问,同时对于不在同一个包中的子类中也可以访问;public修饰的属性或方法外部类中都可以直接访问。
封装提供了一个有效的途径来保护数据不被意外的破坏。相比我们将数据在程序中定义为公用的(public)我们将它们(fields)定义为私有的(private)在很多方面会更好。私有的数据可以用两种方式来间接的控制。第一种方法,我们使用传统的存、取方法。第二种方法我们用属性(property),使用属性不仅可以控制存取数据的合法性,同时也提供了“读写”、“只读”、“只写”灵活的操作方法。
封装
package com.openlab;
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
封装后只能通过set和get方法访问
//save as Test.java
package com.lch;
class Test {
public static void main(String[] args) {
Student s = new Student();
s.setName("vijay"); //设置set
System.out.println(s.getName()); //使用get进行访问
}
}
输出结果
vijay
2.继承
1.什么是继承
是一种java的机制,子类可以继承父类的所有属性和方法;当子类继承父类时。可以重复使用父类中的属性和方法,也可以添加新的属性和方法
继承后,子类能够利用父类中定义的变量和方法,就像它们属于子类本身一样。
单继承:在类层次中,子类只继承一个父类的数据结构和方法,一个类只有一个父类
多继承:在类层次中,子类继承了多个父类的数据结构和方法,一个类允许有多个继承
class B{
……
}
}
class A extends B{
……
}
}
extends关键字用于继承,中文意思延伸,可以理解为,class A extends B;表示A 是B的延伸 ,含义是添加新的功能,在java中被继承的类称为父类或超类,新类叫做子类
上例代码中,A是父类,B是子类。
特点
提高了代码复用性。
让类与类之间产生了关系,继承是多态的前提。
扩展:
子类继承父类,子类拥有了父类的所有属性和方法。
程序验证,父类的私有属性和方法子类是无法直接访问的。当然私有属性可以通过public修饰的get和set方法访问到的,但是私有方法不行。
假设:子类不能够继承父类的私有属性和方法
那么:分析内存后会发现,当一个子类被实例化的时候,默认会先调用父类的构造方法对父类进行初始化,即在内存中创建一个父类对象,然后再父类对象的外部放上子类独有的属性,两者合起来成为一个子类的对象。
所以:子类继承了父类的所有属性和方法或子类拥有父类的所有属性和方法是对的,只不过父类的私有属性和方法,子类是无法直接访问到的。即只是拥有,但是无法使用。
重写(覆盖)
当子类出现和父类一模一样的函数时,当子类对象调用该函数时,会运行子类的内容。如同父类的函数被覆盖一样。
这就是函数的另一个特征,重写(覆盖)。
当子类继承父类,沿袭了父类的方法到子类中,但是子类虽然具有该方法,但是方法的方法体却和父类的不一样,这是没必要定义新的功能,而是使用覆盖特征,保留父类的方法的定义,并重写方法体的内容。
重写的注意事项:
子类要重写父类的某方法时,必须保证子类的权限大于等于父类权限,才可以覆盖,否则编译失败。
静态方法可以被继承,但不能被重写,如果父类中有个静态方法,子类中也有与其方法名、参数类型、参数个数都一样的方法,并且该方法也是静态的,那么该子类的方法会把原来继承过来的方法隐藏,而不是重写。通俗的讲就是父类和子类的方法是两个没有关系的方法,具体调用哪一个方法主要看是哪个对象的引用;这种父子类方法是不存在多态的性质。《Java编程思想》中这样提到"只有普通的方法调用可以是多态的"。
还有一种情况,当父类某方法的权限为private时,子类是不能重写该方法的,但我们可以重新定义和父类该方法一样的方法。
3.多态
1.多态是方法的多态,不是属性的多态(多态与属性无关)
2.多态的存在有三个必要条件:继承,方法重写,父类引用指向子类对象。
3.父类引用指向子类对象后,用该父类引用调用子类重写方法,此时多态就出现了。
package com.openlab.test;
public class TestDt {
public static void main(String[] args) {
Animal animal=new Animal();
animalCry(animal);
Dog dog=new Dog();
animalCry(dog);
Cat cat=new Cat();
animalCry(cat);
}
public static void animalCry(Animal a){
a.shout();
}
}
class Animal{
public void shout(){
System.out.println("动物叫了一声");
}
}
class Dog extends Animal{
public void shout(){
System.out.println("汪汪汪!");
}
}
class Cat extends Animal{
public void shout(){
System.out.println("喵喵喵!");
}
}