面向对象的三大基本特征是什么?------通过代码讲解

一、封装

封装就是隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。对象是封装类的实例,比如张三是人,人是一个封装类,张三只是对象中的一个实例、一个对象)。比如我们日常生活中的小兔子、小绵羊都可以封装为一个类。

  • 封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,以特定的访问权限来使用类的成员。
  • 一旦类的实现者修改了代码(例如把 name 改成 myName), 那么类的使用者就需要大规模的修改自己的代码, 维护成本较高,封装后就从不能随意的修改
 class  Student {

    //限定你只能在类当中进行访问
    private String myName ;   //----------如果一个属性或者方法被private修饰,就只能在类当中使用
    private int age;//---------无特殊要求 所以的属性都设置为私有的



    public void setMyName ( String myName) {  //-------------提供一个公开的接口让外部设置 被private修饰的MyName

//       MyName = MyName;-------------------错误,其实就是 自己给自己赋值  并没有赋值属性  局部变量优先,形参
        this.myName = myName;  //---------- 正确this引用,表示调用该方法的对象
    }                                       //或者当前对象的引用

    public String getMyName ( ) {//-------------提供一个公开的接口让外部获取 被private修饰的MyName
        return this.myName;
    }


    public  void  func1 () {
        System.out.println("func1 ( )");
    }

    public void show() {
        System.out.println("我叫" + this.myName + ", 今年" + this.age + "岁");  //----------被private修饰 ,类内是可以访问的
    }

    //重新 实现了一下 Object类的 toString()方法
    //Object  是 所有类的父类  alt + insert  ->toString()

//    @Override     //注解:这个注解指的是  这个方法是重新写的
//    public String toString() { //  -------------可自动生成
//        return "Student{" +
//                "myName='" + myName + '\'' +
//                ", age=" + age +
//                '}';
 //   }
}

public class TestDemo {
    public static void main(String[] args) {
        Student student  = new Student();
    //  student.MyName= "baozi"; --------------------不可以被访问,只能在类中访问 private修饰了


        student.setMyName("baozi"); //-----------使用public接口设置被private修饰的成员变量    public接口不会被轻易修改,一般较稳定

        String str = student.getMyName();    //-----------public提供了接口 获取private成员变量的值
        System.out.println(str);
        student.show();    //-----------------成员变量修改后 看一下 show一下 看

   //    System.out.println(student);//  自动打印 alt+ insert 选toString

    }
}

二、继承

继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。

  • 使用 extends 指定父类.
  • Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承).
  • 子类会继承父类除了构造方法外的所有
  • 对于父类的 private 的字段和方法,只是拥有,但子类中是无法访问的.
  • 子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用.
  • final 修饰的类不可继承
class Animal {
    protected String name ;//-----成员属性 name  protected 体现了封装与继承 注意:不同包中只有子类才可以访问,相同包随意

    public Animal ( String name ) {
        this.name = name;
        System.out.println("Animal ----------构造器 "+ this.name );

    }

    public void eat() { //成员方法
        System.out.println(this.name + "Animal-----------eat( )");
    }

    private void sleep() { //成员方法
        System.out.println("Animal-----------sleep()");
    }

}
class  Cat extends Animal {  //------猫继承了动物除去构造方法外的所有
    public Cat ( String name ) {
       //必须放在构造器的第一行 和this一致
        super( name );   /**对于继承而言,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要显示的调用父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)*/
        //显示调用了父类的构造方法 不是继承
        super.name = "super 可以访问父类的属性";
        super.eat(); //访问父类的方法
        System.out.println("cat ----------构造器 ");
    }
}
//被final修饰的类是不能被继承了(密封类)
 final class BaoZi extends  Cat {     //多层继承不能超过3层 继承不可以多重
    public BaoZi (String name) {
        super(name);
    }
}
class Bird extends Animal {

    public Bird(String name) {
        super( name );
    }

    public void fly( ) {

        System.out.println(this.name+"Bird-----------fly( )");
    }
}

public class TestDemo {
 public static void main(String[] args) {
        Cat cat = new Cat( "baozi");
        cat.name = "包子"; //猫继承了name属性
        cat.eat();          //继承了吃 方法
        //cat.sleep();  /** 如果private修饰的方法 ,是可以被继承的 但是子类中无法访问 */
    }
}

三、多态

多态同一个行为具有多个不同表现形式或形态的能力。是指一个类实例(对象)的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性

实现多态必须
①父类引用引用子类对象
②父类和子类有同名的重写方法
③通过父类的引用调用这个重写的方法时候 (运行时候绑定)

  • 封装是让类的调用者不需要知道类的实现细节;多态能让类的调用者连这个类(Shape)的类型是什么都不必知道, 只需要知道传过去的对象(cycle)具有某个方法即可.因此, 多态可以理解成是封装的更进一步, 让类调用者对类的使用成本进一步降
  • 可扩展能力更强,使用多态的方式代码改动成本也比较低

class Shape {   // 关注父类的代码, 就能够同时兼容各种子类的情况
    public void draw ( ) {

    }
}

class Cycle extends Shape {
    @Override  //       方法是被重写的 防止重写的时候失误出现命名错误等 提前报错
    public void draw() {
        System.out.println("○");
    }
}

class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("口");
    }
}
class Flower extends Shape {
    @Override
    public void draw() {
        System.out.println("♣");
    }
}

public class Test {
    public static void drawShape (Shape shape ) { //不关心shape这个引用引用了那个对象 只要重写了draw方法 就会发生运行时绑定

        shape.draw(); /** 此时shape调用了哪个draw方法 不知道 取决于它引用的是哪个对象,
                        指向的对象不一样,调用的draw方法也不一样,
                        draw方法因为引用不同对象表现形式不一样  这样就是多态*/
    }
    public static void main(String[] args) {
        Shape shape1 = new Cycle(); //向上转型
        Shape shape2 = new Rectangle();
        Shape shape3 = new Flower();
        drawShape ( shape1);
        drawShape(shape2);
        drawShape(shape3);
    }
}

举个例子
对于, 计算机的CPU/内存/主板/独显/光驱/打印机 有很多功能(方法/行为), 那么到底哪些东西是继承, 哪些东西是接口呢.

首先, cpu/内存/主板 是从大型机开始都必备的, 任何计算机都不能把它们去掉.
所以, 这三样东西是继承的, 也就说笔记本的cpu/内存/主板是继承自微机(PC)的

但是/光驱/呢, 现实上很多超薄笔记本不需要光驱的功能.
如果光驱做成继承, 那么笔记本就必须具有光驱, 然后屏蔽光驱功能, 那么这台笔记本还能做到超薄吗? 浪费了资源.
所以光驱,打印机这些东西就应该做成插件.
然后, 在笔记本上做1个可以插光驱和打印机的接口(usb接口).
也就是说, PC的派生类, 有些(笔记本)可以不实现这个接口, 有些(台式机)可以实现这个接口,只需要把光驱插到这个接口上.
至于光驱是如何实现的,
例如一些pc派生类选择实现蓝光光驱, 有些选择刻录机. 但是usb接口本身并不关心. 取决与实现接口的类.
这个就是现实意义上的多态性.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值