面向对象的语言有三大特点:封装、继承、多态。
1、封装
定义:通过访问修饰限定符对类的成员进行隐藏。
意义:隐藏类的实现细节,从而实现安全性。
访问修饰限定符:
1、private:将属性、方法等设置为私有成员,私有成员只能在本类中使用,可以防止其他类对数据随意修改
2、default:默认属性,程序自带,被修饰的成员只能在本包内使用。
3、proteced:将属性、方法设置为保护成员,保护成员可以在同一包中的子类里使用。(通常用于继承中)。
4、public:将属性方法设置为公有成员,公有成员不仅可以在本包中使用在其它包中也能够使用,通俗的讲就是:哪都能用。
static关键字
修饰内容:成员变量、成员方法
主要作用:将成员变量和成员方法设置为静态,使其不依赖对象的引用,即被其修饰的成员变量和方法是类所有的,是所有对象共享的,因此也叫类变量和类方法。
开辟空间的时间:类加载时开辟空间。
访问方式:类名.xxx。
注意事项:静态方法内部不能直接调用非静态成员方法和非静态成员变量。
代码:
public class Animal {
static String name;//静态成员变量
static void eat(){//静态成员方法
}
public static void main(String[] args) {
//访问方式:类名.xxx
Animal.name = "狗";
Animal.eat();
}
}
2、继承
定义:对子类的共性进行抽取形成父类,子类会继承父类的成员方法和成员变量。
意义:达到了代码的复用效果,节省了开发时间。
关系:子类和父类是一种is-a(an)的关系。例如:
Dog(子类) is an Animal(父类)
语法:通过extends关键字,可以声明类B(子类)继承于类A(父类),代码如下:
Class A{
...
}
Class B extends A{
...
}
super关键字
定义:一个关键字!!!,让别人看到就知道这样访问的是父类的属性和方法,提高代码的可读性。
1、成员变量和成员方法
当父类和子类出现同名成员变量和成员方法时,在子类当中访问这个变量或方法,会优先访问子类自己的,如果要访问父类的就要使用super关键字。
代码如下:
public class Animal {
String name = "动物";
public void eat(){
System.out.println("吃饭");
}
}
class Dog extends Animal{
String name = "狗";
public void eat(){
System.out.println("吃狗粮");
}
public void print(){
//子类的
System.out.println(name);
eat();
//父类的
System.out.println(super.name);
super.eat();
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.print();
}
}
注意事项:1、只能在非静态方法中使用。
2、必须在子类方法中使用。
2、构造方法
子类继承父类之后一定要先帮助父类进行构造,然后再构造子类自己。在子类中帮助父类构造需要使用super(参数)调用父类的构造方法。
代码如下:
class Animal {
String name;
int age;
//父类的构造方法
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
}
class Dog extends Animal{
String brand;//种类
//子类的构造方法
public Dog(String name, int age, String brand) {
super(name, age);//调用父类构造方法
this.brand = brand;
}
}
3、super和this
相同:1、都是Java的关键字。2、只能在类的非静态方法中使用,用来访问非静态成员和字段。3、在构造方法中调用时,必须是构造方法的第一条语句,且不能同时存在。
不同:this是当前对象的引用,super相当于是子类对象从父类继承下来的部分成员的引用。
3、多态
定义:当我们引用的对象不一样,调用同一个重写方法表现的行为不一样,这种思想叫多态。
多态发生的条件:发生动态绑定是发生多态的基础。
发生动态绑定:1、发生向上转型(父类引用,引用了子类对象)。
语法:父类 父类引用 = new 子类对象。
代码如下:
Animal animal = new Dog();//向上转型
2、子类和父类有重写方法
重写方法:
1、方法名相同。
2、参数相同(个数、类型、顺序)。
3、返回值类型可以不同,但是必须是父子类型。
class Animal {
public void eat(){
System.out.println("吃饭");
}
Animal dog(){
return new Animal();
}
}
class Dog extends Animal {
public void eat(){//重写eat方法
System.out.println("吃狗粮");
}
Dog dog(){//重写dog方法
return new Dog();
}
}
重写注意事项 :
1、被private、static、final修饰的方法不能重写。
2、子类重写方法的权限一定要大于父类的。
3、方法返回值可以不同,但必须是父子关系。
4、构造方法不能重写。
3、通过父类引用调用父类、子类重写的方法。
代码如下:
public static void main(String[] args) {
Animal animal = new Dog();//向上转型
animal.eat();
System.out.println(animal.dog() instanceof Dog);//判断这个对象是否属于Dog
}
结果:
通过父类引用调用了重写方法,都使用了子类的重写方法,这就说明发生了动态绑定。
下面我们通过代码更深层地感受多态的思想 :
public class Test {
public static void drawMap(){
//创建对象
Ract ract = new Ract();
Circle circle = new Circle();
Flower flower = new Flower();
Shape[] shape = {circle,ract,circle,flower,ract,circle};//通过数组向上转型
for (Shape shape1:shape){
shape1.draw();
}
}
public static void main(String[] args) {
drawMap();
}
}
class Shape{
public void draw(){
System.out.println("画图形");
}
}
class Ract extends Shape{
@Override
public void draw() {
System.out.println("矩形");
}
}
class Circle extends Shape{
@Override
public void draw() {
System.out.println("圆形");
}
}
class Flower extends Shape{
@Override
public void draw() {
System.out.println("❀");
}
}
结果:
如果我们没有多态的思想,我们需要通过很多的if-else语句来解决这个问题。
代码如下:
public static void drawMap3(){
Ract ract = new Ract();
Circle circle = new Circle();
Flower flower = new Flower();
Shape[] shape = {circle,ract,circle,flower,ract,circle};//向上转型了
for (Shape shape1:shape){
if ((shape1 instanceof Circle)){
circle.draw();
}
else if (shape1 instanceof Ract){
ract.draw();
}
else if (shape1 instanceof Flower){
flower.draw();
}
}
}
因此,多态的思想降低了代码的圈复杂度,而且可拓展性更强,但是它会使代码运行效率降低