面向对象3

今天我们继续来讲一下上次封装的拓展部分。

单例模式

要讲单例模式前,我们简要的说一下概念。

设计模式:前人总结出的解决某类的问题的最优方案-----模板。

单例模式:需要某个类在整个应用程序中,只创建一个对象。

正如同封装的思想一样,单例模式为的是希望别人不能随意的创建对象,固定只创建一个对象。

而单例模式中有懒汉单例,如下图

以及饿汉单例,如下图。

懒汉单例正如其名,只有在调用方法是才会创建对象。饿汉单例还有一种叫法叫做急切式单例,正是因为它在调用类时就已经创建了对象。而懒汉单例会出现一些线程安全性的问题,这个我们以后讲到再说。

面向对象特征——继承

继承:继承是面向对象程序设计不可缺少的设计思想,是实现代码可重用的根基,是提高代码可扩展性的主要途径。

继承有以下4个要点:
1 继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并能扩展新的能力。
2 在JAVA中使用extends关键字来表示继承关系。
3 JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个直接父类。
4 继承之后子类可以调用父类的所有非私有属性和非私有方法.

总而言之,继承就是,子类继承父类,使用父类中已经实现好的功能,而且子类还可以扩展自己的功能。

这也正体现出了面向对象的设计宗旨:代码复用性高、代码扩展性强。

那么何时使用继承呢?

继承就如同现实世界中,比如猫和狗都算是动物类。而猫类和狗类就是子类,动物类就算是父类。而继承就是将子类共有的属性和行为放到父类中。

我们首先在代码中定义出Animal类。

public class Animal {
   private String name;
    private int age;

    public void showInfo(){
        System.out.println("狗的名字是"+name+"年龄"+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;
    }

}

然后我们定义Dog类并且继承父类Animal类。

public class Dog extends Animal{


}

随后在主方法中创建个Dog类对象就可以使用Animal类内的变量以及方法了。

public class Text {
    public static void main(String[] args) {
        Dog dog=new Dog();
        dog.setAge(10);
        dog.setName("小黑");
        dog.showInfo();
    }
}

 以上便是简单的讲解了一下继承extends的使用。

继承的传递性
C类从B类继承,B类又从A类继承
那么C类就具有B类和A类的所有非私有属性和非私有方法
当一个没有继承任何一个类时,jvm会默认让类继承Object类
Object是 java为所有类提供的基类

 Java中一个类,只能直接继承一个父类,不允许多继承,但是支持多级继承传递。

像这里我们在Dog类中定义一个特别的run()方法。

public class Dog extends Animal{
    public void run(){
        System.out.println("狗正在奔跑");
    }

}

 我们有定义一个新类使其继承Dog类

public class Xtq extends Dog{
    

}

 最后主方法中我们可以看到,Xtq类既可以使用Animal类中的方法又可以使用Dog中的方法。

public class Text {
    public static void main(String[] args) {
        Xtq xtq=new Xtq();
        xtq.setAge(10000);
        xtq.setName("哮天犬");
        xtq.showInfo();
        xtq.run();
    }
}

 

 

 super关键字

 super关键字用途:
 使用super关键字访问父类成员
1.用super.成员变量名来引用父类成员变量
2. 用super.方法名(参数列表)访问父类的方法。
3. 用super.构造方法(参数列表)访问父类构造方法

注意!不要把super误认为是父类对象.在创建子类对象时,不会创建父类对象。只会将父类中的信息加载到子类对象中存储

 继承中的构造方法

子类构造方法会先调用父类构造方法。
使用super关键字调用父类任意一个构造方法,必须写在构造方法的第一行。
如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法。

 这里我们在Animal类中创建了无参的构造方法和有参的构造方法。而继承Object类其实写不写无所谓,因为前面说过第一个类没有继承任何类时,他会默认继承Object类。

public class Animal extends Object{

    private  String name;
    private   int age;

    public Animal() {
        super();
        System.out.println("动物类中无参的构造方法");
    }
    public Animal(String name,int age) {
        super();
        this.name = name;
        this.age = age;
        System.out.println("动物类中有参的构造方法");
    }
}

 Dog类也同上创建两种构造方法。此刻注意Dog类中独有属性color,在有参构造方法中super()没有color,因为父类Animal类中没有这个属性。而在无参构造方法中,super()其实可以省略,Java中是默认调用的。

public class Dog extends Animal{
    private String color;
    public Dog(){
        super();
        System.out.println("狗类的无参构造方法");
    }

    public Dog(String name,int age,String color){
        super(name,age);
        this.color = color;
        System.out.println("狗类的有参构造方法");
    }

}
public class Xtq extends Dog{
    public Xtq(){
        super();
        System.out.println("哮天犬类的无参构造方法");
    }

    public Xtq(String name, int age, String color){
        super(name,age,color);
        System.out.println("哮天犬类的有参构造方法");
    }

}

 最后在主方法中调用一个无参的构造方法以及一个有参的构造方法。

public class Text {
    public static void main(String[] args) {
        Xtq x1=new Xtq();
        Xtq x2=new Xtq("哮天犬",10000,"黑色");
    }
}

 以下是运行结果:

 

 看到结果我们可以发现,在多级继承中,一级的父类的构造方法是先于所有子类被调用的。因为创建子类对象后,子类对象可以访问父类的信息,所以在初始化子类之前,必须先初始化父类

 方法的重写

 重写(Override)
 应用场景:
当父类的方法实现不能满足子类需求时,可以对方法进行重写。
 在子类中可以根据需要对从基类中继承来的方法进行重写。
 方法重写规则:
 1.方法名相同、参数列表相同;
 2. 返回值类型相同;
 3.访问权限不能小于父类权限;
注意:构造方法,静态方法不能重写,成员变量不存在重写

 举个栗子:

public class Dog extends Animal{
    private String color;
    public void eat(){
        System.out.println("狗正在吃饭");
    }

 这里重写了父类中eat()方法,注意要加上@Override

@Override
    public void eat(){
        System.out.println("神狗正在用餐");
    }

 

 抽象类

 抽象方法:
抽象方法是一种特殊的方法:它只有声明,而没有具体的实现.

抽象方法必须用abstract关键字进行修饰.

 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法。
 用abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成抽象类。
 特点:
1.抽象类不能被实例化,但可以有构造方法,因为抽象类中含有无具体实现的方法,
所以不能用抽象类创建对象。
2. 抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。否则,该类也必须声明为抽象类。

 抽象类就如同一个模糊的概念,需要其子类进行各种各样的描述。

 我们在定义抽象类Animal,抽象类中可以没有抽象方法,但抽象方法一定要在抽象类中。

public abstract class Animal {

  
public abstract void go();
}

 而在其子类Dog类中,要么将其定义成抽象类,要么就要实现父类中的抽象方法。

public class Dog extends Animal{

    @Override
    public void go() {
        System.out.println("狗狗在运动");
    }
}

 在调用的时候,就要用子类去调用,不能用父类去调用。

 public static void main(String[] args) {
        new Dog().go();
        
    }

 抽象类,抽象方法,在软件开发过程中都是设计层面的概念。也就是说,设计人员会设计出抽象类,抽象方法,程序员都是来继承这些抽象类并覆盖抽象方法,实现具体功能。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值