面向对象中的一些概念的理解

今天回顾的内容,可能相对于前面的内容来说在理解上需要花费一点功夫,但面向对象也是属于打基础的部分,学好虽然不能够加分,但是没有掌握到这方面的知识,在后续的基础学习中,会有一些问题。那,我们开始回顾今天的内容吧!!

1. 构造方法

特点:与类同名而没有返回值类型

作用:创建对象

package cn.tedu.object;

public class PersonDemo {
    public static void main(String[] args) {
        //构造方法  --- 创建对象的
        //调用构造方法创建 Person 对象
        Person p = new Person("翠花");
        p.name = "如花";//对象点出来的是一个成员变量
        p.eat();

        Person p2 = new Person();
        p2.eat();
    }
}

class Person{

    String name;
    int age;
    char gender;
    String no; //身份证号,数字,还很多有的人的后面是 x

    //在类中没有手动指定构造方法的时候,那么在编译的时候会自动添加一个无参的构造方法
    //没有返回值类型,与当前类同名
    //构造方法中可以写 return,用于规避一些不合常理的数据
    public Person(){
    }

    //在代码中手动指定了含参构造,那么就不会再默认添加无参构造
    public Person(String name){//开发了网站,用的人都要注册,写一个 user 类,用户的基本信息创建的时候就要写进来
        //遵循就近原则
        this.name = name;  // Warning  --- 警告 --- 智能工具编译到这儿的时候认为这个地方可能存在问题,
                      //但是不影响程序的正常运行
    }

    //Person p = new Person("珠子",-18);
    public Person(String name,int age){
        this.name = name;
        if(age < 0){
            return;
        }
        this.age = age;
    }

    public void eat(){
        System.out.println("吃饭");
    }
}

2. this 关键字

this 关键字在类中调用本类里面的属性和方法,代表当前在活动的对象。

2.1 this 语句 -> this(参数列表) - 表示在本类的构造方法中调用本类对应形式的其他构造方法 - this 语句必须放在构造方法的第一行

package cn.tedu.object;

public class ThisDemo {
    public static void main(String[] args) {
        Student s1 = new Student("Amy");
        System.out.println("s1:" + s1);
        Student s2 = new Student("Sma");
        System.out.println("s2:" + s2);
        s1.name = "Amyy";
    }

}
class Student{
    String name;
    int age;
    String no;//学号

    //用 this 代替一个具体的对象
    //this 代表当前在活动的对象
    //this 在本类中调用本类中的属性和方法
    public Student(String name){

        this.name = name;
        System.out.println("this:"+this);
    }

    public Student(String name, int age){

    }

    public Student(String name, int age, String no){
        //this 调用的普通方法而不是构造方法
        //this.Student(name,age);
        //this(参数列表) --- this 语句
        //表示调用本类中对应形式的构造方法
        //必须放在构造方法的首行
        this(name,age);
        this.no = no;
    }
}

3. 代码块

构造代码块:定义在类中用 { }包起来的代码 --- 在创建

局部代码块:定义在方法中用 { }包起来的代码 --- 提高了栈内存的利用率

package cn.tedu.object;

public class CodeDemo {
    public static void main(String[] args) {
        Baby b1 = new Baby();
        Baby b2 = new Baby("铁蛋");
    }

}
//定义一个代表婴儿的类
class Baby{

    String name;

    //构造代码块/初始化代码块
    //无论利用哪个构造方法创建对象,构造代码块都会先于构造方法执行
    //如果每一个构造方法都有一些要初始化的操作,可以将它们提取到构造代码块中执行
    {
        this.cry();
        this.eat();
    }

    public Baby(){
        System.out.println("running~~~");
    }

    public Baby(String name){
//        this();
        this.name = name;
        //this.cry();
        //this.eat();

    }

    public void cry(){
        System.out.println("这个婴儿在哇哇的哭");
    }

    public void eat(){
        System.out.println("这个小孩在吃奶");
    }
}

4. 面向对象的特征

封装、继承、多态(抽象,一些少部分公司会问这个)(而 Java 语言的特征,第一条,简单易学(先讲 C 语言的什么什么,再推导出 java 的简单易学),完全面向对象,安全可靠,可移植性)

 4.1 封装

将代码进行提取和总结,抽取成不同的形式 --- 封装

体现形式:方法(利用方法名直接反复调用相同的代码)、类(属性的私有化 - 将属性限制为私有的,然后提供对外的设置和获取的方法,然后在方法中进行限制使数据更加符合常理)

优势:提高了代码的复用性,保证了数据的合法性

权限修饰符

指在 Java 中限定使用范围的关键字


 

本类中

子类中

同包内中

其他类中

public

可以

可以()

可以(你的室友)

可以

protected(你自己的一些东西,你们寝室的扫帚)

可以

可以

可以

不可以(其他寝室的,来抢劫啊)

默认(没有给定的形式)(你们家的门,或者窗)

可以

同包子类可以,不同包子类不行

可以

不可以(你来弄,入室抢劫啊)

private(相当于自己的小秘密,私房钱,青春回忆)

可以

不可以

不可以

不可以(走在路上一人说给我点钱花呗,不行)

关于 Protect 修饰符的一些理解:

package cn.tedu.extendsx.b;

import cn.tedu.extendsx.a.A;

public class E extends A{
    public static void main(String[] args) {

        D d = new D();
        //对象的声明类是 D类,所以d对象所对应的子类是 D类
        //因此d对象使用 m方法需要在对应的子类 D类中使用
        //子类对象使用的时候必须在对应的子类中使用
        //d.m();
    }

}

//public class E{
//    public static void main(String[] args) {
//        D d = new D();
//        //虽然D通过继承A可以使用A类中m方法,但是m方法最终定义在A类中
//        //m方法的权限是protected:本类中、子类中、同包类中
//        //m方法的本类是A类,E和A是本类中? --- 不是
//        //m方法是在E类中,E是A的子类吗? --- 不是
//        //E类所在的包是b包,A类所在的包是a包,所以E和A是同包类吗1?---不是
//        //d.m();
//    }
//}

练习:定义一个类表示矩形(长方形),提供获取周长和面积的方法

package cn.tedu.fengzhuang;

public class Rectangle {
    public static void main(String[] args) {
        GetRectangle rec = new GetRectangle(2, 4);
        System.out.println("周长:"+rec.getLong()+" 厘米,面积:"+rec.getSqure()+" 平方厘米");
    }
}

class GetRectangle{

    private double width;
    private double height;

    public double getWidth() {
        return width;
    }
    public double getHeight() {
        return height;
    }

    public GetRectangle(double width, double heigth){
        if(width <= 0 || heigth == 0)
            return;
        this.width = width;
        this.height = heigth;
    }

    public double getLong(){
        return 2 * (width + height);
    }

    public double getSqure(){
        return width * height;
    }
}

4.2 继承

如果一些类中含有相同的代码,那么可以将这些相同的代码提取到一个新的类中,然后通过 extends 关键字让原来的类和新的类产生关系 --- 继承。

通过继承,原来的类就称之为了子类(派生类),新的类就成了父类(超类/基类)。

子类通过继承父类可以使用父类中的一部分方法和属性

注意:子类继承了父类的全部的数据域(方法 + 属性),但是继承之后只有一部分数据域对子类可见。

在 Java 中,支持的是类和类之间的单继承 -> 一个子类只能继承一个父类,但是一个父类可以有多个子类

单继承一定优于多继承吗?  --- 不对,C++ 中采用的是多继承,但是现在几十年的时间了,C++ 仍然采用多继承。

---比如,一个人要到一个医院上班(这个 Person 继承这个 Doctor 类(有一个treat() 方法)),要到医院去上课(这个 Person 继承 Teacher 类(有一个 teach() 方法)),如果是单继承,选择继承了 Doctor 了,Teacher 类中的代码就要在 Person 中再写一遍。

---多继承比单继承能够更好的提高代码的复用性

---再比如,如果是多继承,无论是 Doctor 还是 Teacher 都有一个相同名字 salary() 方法(这两个类的计算方法不一样),但是我想知道工资(p.salary() 并不确定是哪一个)

---多继承导致在调用方法的时候可能产生歧义

优势:提高代码的复用性,避免方法的调用产生歧义

  4.2.1 Super 关键字

在子类中用于表示父类对象的引用,可以在子类中调用父类中的方法的属性。

super 语句 --- 子类在继承父类之后,子类的构造方法中会含有一个 super 语句。如果没有没有手动指定 super 语句,那么默认使用super()调用父类无参的构造;如果父类只提供了含参构造,那么父类就必须手动提供对应形式的 super 语句 --- super 语句必须在子类构造方法的首行

  4.2.2 方法的重写/覆盖

在父子类中存在了方法签名相同的非静态方法。遵循“两等两小一大 ”原则:

1.方法签名相同

2.如果父类中的方法的返回值类型是基本类型/void,那么子类重写的方法的返回值类型与父类一致

3.如果父类中的方法的返回值类型是引用类型,那么子类在重写方法的时候,返回值类型要么与父类一致,要么是父类方法返回值类型的子类

class A{}

class B extends A{}

class C{

public A m(){return null;}

}

class D extends C{

public B m() { return null;}

}

4.子类重写的方法的权限修饰符的范围要大于等于父类中对应方法的权限修饰符的范围

class A{

public void m(){ }

}

class B extends A{

public int m(){ return 0;}

}

注意:如果父类中的方法用 private 修饰,那么这个方法对子类不可见,所以此时与子类中的方法构不成重写

package cn.tedu.extendsx;

public class ExtendsDemo {
    public static void main(String[] args) {
        Cat c = new Cat();
        //通过继承,子类可以使用父类中的属性和方法
        c.eat();
    }
}

//父类
class Pet{
    String name;
    String color;

    public Pet(String name){
    }

    public Pet(String name, String color){
    }

    public void eat(){
        System.out.println("在吃东西");
    }
}

//利用extends关键字让原来的类与提取出来的新的类产生了联系  --- 继承
//子类
class Cat extends Pet{

    public Cat(){
        //在子类构造方法中,如果没有手动指定,那么默认添加super()
        //super 语句 --- 表示调用父类中对应的形式的构造方法
        //super() --- Pet()
        //如果父类中只提供含参构造,那么子类中就必须手动提供对应形式的构造方法
        super("波斯猫");
    }

    public void drink(){
        //通过super代表父类对象,通过父类对象调用父类中的属性和方法
        super.eat();
        System.out.println("吃完东西喝点水");
    }

    public void catches(){
        System.out.println("这只猫在挠沙发");
    }
}
//子类
class Dog extends Pet{

    public Dog(){
        //super("金毛","绿色");
        super("二哈");//this();这两个不能够同时出现
        super.color = "绿色";
    }

    public void bark(){
        System.out.println("这只狗在叫");
    }
}

4.3 多态

(在未来的基础阶段你感觉不到用处,但在后面的大数据中,解耦会涉及到)一个接口建了之后,实现的具体方式就由其他分别体现(使用子类都统一用一个父类接收,在父类中判断接收的具体对象),两个接口,一个加分,一个加密,子类造型成父类,在父类中判断是不是这个子类,是就加分。编译时,不管子类是什么,后面交给程序员就具体实现相应的类。只有在运行时,便于维护。

4.3.1 编译时多态:方法的重载

add(2,4)  -> add(int, int);

add(3,1,7) ->add(int, int, int)    //编译时期就知道这个方法有没有

4.3.2 运行时多态:向上造型和方法的重写 --- 基于继承的

注意:如果使用向上造型来创建对象,那么这个对象所能调用的方法看的是父类中的声明,方法如何执行看的是子类中的实现过程

package cn.tedu.duotai;

public class DuotaiDemo {
    public static void main(String[] args) {
        //父类声明对象,用子类创建对象,利用向上造型来创建的这个对象
        //对象在编译过程中并不会检查到底使用的是哪个子类,在编译期间只会检查声明类和实现类之间是否有继承关系,
        //直到运行的时候才会检查具体的子类然后根据子类来分配空间
        Pet p = new Cat();
        //p.catches();
        //当使用向上造型来创建对象的时候,只能使用父类中声明的方法,而不能使用子类中单独定义的方法
        p.eat();
    }

}

class Pet{
    public void eat(){
        System.out.println("在吃东西~~~");
    }
}

class Cat extends Pet{

    @Override
    public void  eat(){
        System.out.println("这只猫在吃草~~~");
    }

    public void catches(){
        System.out.println("这只猫在抓老鼠");
    }
}

class Dog extends Pet{

    @Override
    public void eat(){
        System.out.println("这只狗在吃猫~~~");
    }

    public void bark(){
        System.out.println("这只狗在叫");
    }
}

重写的理解

1.子类重写的方法的权限修饰符的范围要大于等于父类中对应方法的权限修饰符

2.如果父类中的方法的返回值类型是引用类型,那么子类在重写方法的时候,返回值类型要么与父类一致,要么是父类方法返回值类型的子类

注意:Java 中所有的基本类型之间没有继承关系,之所以能够自动提升,是因为所表示的范围是否能够包含

package cn.tedu.extendsx;

public class OverrideDemo {
    private void mian() {
        // TODO Auto-generated method stub
        Teacher t = new Teacher();
        //子类对象是调用重写之后的方法
        t.work();
    }
}
//表示职业的类
class Profession{
    public void work(){
        System.out.println("在工作~~~");
    }
}

class Teacher extends Profession{
    //父类中的方法写的比较简单,子类需要对父类中的方法进行扩展
    @Override  //@ 注解
    //@Override 这个注解是用于校验当前方法是否构成了重写
    public void work(){
        System.out.println("这个老师在诲人不倦");
    }
}

原文地址:https://www.cnblogs.com/tangdiao/p/9456494.html

时间: 2024-08-29 20:43:06

面向对象中的一些概念的理解的相关文章

面向对象中的封装性怎么理解?

封装这个解释,我一直喜欢用CPU作为例子CPU把所有的电阻电容门电路等都封装起来,只留出一些管脚(接口)让用户使用,CPU能暴露什么,不能暴露什么,是生产商设计决定的,用户不能直接操作CPU的电阻电容等等,但可以通过給管脚适当的电压来控制电阻电容等,也就是说用户不能直接访问CPU的属性,但是可以通过方法修改CPU的属性的值同样的一个类也是把属性算法(逻辑处理)封装起来,只留必要的方法(接口)让用户使用,一个类该暴露什么,不该暴露什么,由类的设计者根据需求设计决定的.private属性用户不能直接

iOS项目中工作空间Workspaces概念的理解

我在之前的一篇博客中讨论过Eclipse和Android Studio的工作空间问题,并做了一定的区别.其实只要理解并会使用前两者,Xcode中的工作空间也就不难理解了.我们通过实际的操作步骤来理解Xcode的工作空间. (1)在Xcode中点击:File-->New-->Workspace.   在Save as中输入工作空间的名称.并选择存放的目录: . (2)去刚才的目录下查看,发现多了一个MyApplication.xcworkspace文件.该文件就是工作空间.先关闭Xcode,双击

RxJava 2 0中backpressure 背压 概念的理解

英文原文:https://github.com/ReactiveX/RxJava/wiki/Backpressure Backpressure(背压.反压力) 在rxjava中会经常遇到一种情况就是被观察者发送消息太快以至于它的操作符或者订阅者不能及时处理相关的消息.那么随之而来的就是如何处理这些未处理的消息. 举个例子,使用zip操作符将两个无限大的Observable压缩在一起,其中一个被观察者发送消息的速度是另一个的两倍.一个比较不靠谱的做法就是把发送比较快的消息缓存起来,当比较慢的Obs

深入分析面向对象中的对象概念(转)

OOP:面向对象编程,一提到面向对象,大家可能就想到类,接口.一说特性,大家可能张口就来:继承.封装.多态,那么到底什么样的对象(类)才是真正意义上的对象呢?特别是现在流行的DDD领域驱动设计思想,讲究职责划分,那么如何定义一个对象(类)它应该具有的一些特性.行为方法及承担责任成为关键. 一个看似简单的问题,其实也是耐人思索,之前也在网上看到一些人关于讨论类的设计问题,认为设计类时不应该考虑数据库,我觉得这只是实现真正的面向对象设计的基础,也是前提条件,大多数程序员之前都是受面向过程编程思想的影

python面向对象中的__init__方法怎么理解?

我们在学习python类的时候,总会碰见书上的类中有__init__()这样一个函数,很多同学百思不得其解,其实它就是python的构造方法. 构造方法类似于类似init()这种初始化方法,来初始化新创建对象的状态,在一个对象呗创建以后会立即调用,比如像实例化一个类: f = FooBar() f.init() 使用构造方法就能让它简化成如下形式: f = FooBar() 你可能还没理解到底什么是构造方法,什么是初始化,下面我们再来举个例子: class FooBar: def __init_

深入分析面向对象中的对象概念

OOP:面向对象编程,一提到面向对象,大家可能就想到类,接口.一说特性,大家可能张口就来:继承.封装.多态,那么到底什么样的对象(类)才是真正意义上的对象呢?特别是现在流行的DDD领域驱动设计思想,讲究职责划分,那么如何定义一个对象(类)它应该具有的一些特性.行为方法及承担责任成为关键. 一个看似简单的问题,其实也是耐人思索,之前也在网上看到一些人关于讨论类的设计问题,认为设计类时不应该考虑数据库,我觉得这只是实现真正的面向对象设计的基础,也是前提条件,大多数程序员之前都是受面向过程编程思想的影

关于数字信号处理中的一些概念的理解

1,卷积:卷积的时域解释可类比为摔跤后疼痛感的持续,不同时刻的输入x(m)都对输出有影响,影响的大小取决于m时刻后的影响因子h(n-m),则此时(n时刻)的输出受m时刻的影响为x(m)*h(n-m),再考虑其他时刻的影响,则卷积公式得出. 从频域理解的话就是系统输出的傅里叶变换=输入的傅里叶变换*频率响应因子. 2,傅里叶变换:个人理解所谓的傅里叶变换就是通过数学上的累加将时间因子消去只留下频率因子的结果. 3,数字频率,模拟频率,采样频率的关系:w=2pi*f/fs;其中w是数字频率,f是模拟

深入分析面向对象中的封装作用

之前我(梦在旅途)发表过一篇名为<深入分析面向对象中的对象概念>的文章,里面主要讲解了类与对象的关系以及对象的概念.状态.行为.角色几个知识点,让大家对对象有了一些深入的了解,而本文则再来谈谈面向对象的三大特性之一:封装,封装是实现面向对象的基础,深入的理解封装的特性,有利于我们能更好的领悟面向对象的思想以及实现面向对象编程.以下均为本人凭借多年开发经验总结的个人观点,大家若发现有误或不足的地方,欢迎指正和交流,谢谢! 一.什么是封装? 顾名思义,封:封闭,装:装起来,将具体的实现细节装到一个

OSPF部分概念个人理解

以下为个人在学习OSPF过程中对这些概念的理解,有不同理解大家互相沟通交流! 1.邻居关系和邻接关系有什么区别? 邻接关系一定是邻居关系,但邻居关系不一定是邻接关系. BMA环境下(在以太网环境.同一个广播域内),两个DRother路由器之间的状态即为邻居状态(two-way) DR.BDR之间:DR和BDR与DRother之间建立的均为邻接关系(Full). 2.OSPF支持的网络类型有哪些? P2P(点到点网络):eg:PPP.HDLC P2MP(非广播点到多点网络):eg:不完全连接的帧中