程序员成长之路(Day 24)

本文详细介绍了面向对象的设计思想,包括基本概念、基本原则,如抽象、封装、委托等,以及面向对象分析与设计的过程。同时,深入探讨了Java中的类、成员变量和构造方法的定义与作用。此外,通过LintCode刷题展示了Java在实际问题中的应用,如位运算、圆形周长计算等。
摘要由CSDN通过智能技术生成

目录

学习目标:

学习内容:

面向对象设计思想:

        面向对象的基本概念:

        面向对象的定义:

        面向对象的基本思想:

        面向对象的基本原则:

1.抽象

2.封装

3.委托

4.分类

5.泛化

6.消息通信

7.关系机制

8.复杂性控制

面向对象的分析与设计:

        OOA(分析):

        OOD(设计):

Java与面向对象:

类中成员变量的定义与意义:

构造方法的定义和调用:

        定义:

        构造方法的使用:

        构造方法的作用:

LintCode刷题:

·位运算左移三位

··圆形周长

·最大二叉树

· 最后一个单词的长度

·判断连接 ​

 ·乱序字符串

学习时间:

学习产出:


学习目标:

  • 面向对象设计思想
  • 面向对象的分析与设计
  • Java与面向对象
  • 类中成员变量的定义与意义
  • 构造方法的定义和调用
  • 面向对象的封装特性
  • 局部变量和成员变量的作用域问题
  • 静态属性、静态方法、静态代码块
  • 面向对象的继承特性
  • 继承中构造方法的细节
  • 面向对象的多态特性
  • 抽象方法与抽象类
  • 接口

学习内容:

面向对象设计思想:

        面向对象的基本概念:

        面向对象方法的解决问题的思路是从现实世界中的客观对象(如人和事物)入手,尽量运用人类的自然思维方式来构造软件系统,这与传统的结构化方法从功能入手和信息工程化方法从信息入手是不一样的。在面向对象方法中,把一切都看成是对象。

        面向对象的定义:

         从程序设计方法的角度看,面向对象是一种新的程序设计范型(paradigm),其基本思想是使用对象、类、继承、封装、聚合、关联、消息、多态性等基本概念来进行程序设计。是一种运用对象、类、继承、封装、聚合、关联、消息、多态性等概念来构造系统的软件开发方法。

        面向对象的基本思想:

  • 从现实世界中客观存在的事物出发来建立软件系统,强调直接以问题域(现实世界)中的事物为中心来思考问题、认识问题,并根据这些事物的本质特征,把它们抽象地表示为系统中的对象,作为系统的基本构成单位。这可以使系统直接映射问题域,保持问题域中事物及其相互关系的本来面貌(对象)
  • 用对象的属性表示事物的性质;用对象的操作表示事物的行为。(属性与操作)
  • 对象的属性与操作结合为一体,成为一个独立的、不可分的实体,对外屏蔽其内部细节。(对象的封装)
  • 对事物进行分类。把具有相同属性和相同操作的对象归为一类,类是这些对象的抽象描述,每个对象是它的类的一个实例。 (分类)
  • 复杂的对象可以用简单的对象作为其构成部分。(聚合)
  • 通过在不同程度上运用抽象的原则,可以得到较一般的类和较特殊的类。特殊类继承一般类的属性与操作,从而简化系统的构造过程及其文档。(继承)
  • 类具有封闭性,把内部的属性和操作隐藏起来,只有公共的操作对外是可见的。 (类的封闭性)
  • 对象之间通过消息进行通讯,以实现对象之间的动态联系。   (消息)
  • 通过关联表达类(一组对象)之间的静态关系。(关联)

        面向对象的基本原则:

1.抽象

        过程抽象:任何一个完成确定功能的操作序列,其使用者都可把它看作一个单一的实体,尽管实际上它可能是由一系列更低级的操作完成的。

        数据抽象:根据施加于数据之上的操作来定义数据类型,并限定数据的值只能由这些操作来修改和观察。

客观事物->对象->类->一般类

不同开发阶段需要进行不同程度的抽象,便于实现模块的可替换性

2.封装

        把对象的属性和操作结合成一个独立的系统单位,并尽可能隐蔽对象的内部细节。只是向外部提供接口,降低了对象间的耦合度。

封装的意义:

  • 使对象能够集中而完整地描述并对应一个具体事物。
  • 体现了事物的相对独立性,使对象外部不能随意存取对象的内部数据,避免了外部错误对它的“交插感染”。
  • 对象的内部的修改对外部的影响很小,减少了修改引起的“波动效应”。
  • 公开静态的、不变的操作,而把动态的、易变的操作隐藏起来。

封装机制保证:数据不能被对象的使用者直接访问。只允许通过由对象提供的方法或代码访问数据。

3.委托

        借助消息传递,工作可从一个对象(客户)传递到另一个对象(代理),因为从客户的观点,代理具有客户所需要的操作。工作连续地传递,直到到达了既有数据又有方法(代码)能完成这项工作的对象。 

注意:委托是执行任务的权利,而不是责任。

4.分类

        把具有共同性质的事物划分为一类,得出一个抽象的概念。分类帮助我们组织我们所生活的复杂世界。我们可以对在一个特殊分类中的对象做一些假设。如果一个对象是分类(类)的一个实例,它将符合该分类的总体模式。所有的对象都是类的实例。实例能够在运行时被产生(初始化)或销毁(删除)。对象怎样提供操作,由该对象为其实例的类所决定。这样,同一个类的所有对象在响应特定的操作请求(功能调用)时使用相同的方法

5.泛化

        无多态性的泛化:类可以由层次继承结构所组织。在该结构中,子类将从位于层次结构高层的父类中继承属性、操作和关系。抽象的父类是指仅用来定义子类的超类。这样,抽象类就没有直接的实例。

有多态的泛化:可以使用层次继承结构组织类,子类可以继承位于层次结构的高层的父类的属性、操作和关系。然而,子类可以定义它自己的操作来代替其任何超类的同名操作。

6.消息通信

 即要求对象之间只能通过消息进行通讯。消息传递机制与函数调用机制的区别 :

  • 在消息传递机制中,每一个消息被发送给指定的接收者(对象)。在命令式编程范型中,函数调用机制没有指定的接收者。
  • 消息的解释(用来完成操作请求的方法或操作/代码集)依赖接收者,并且因接收者的不同而异。
  • 在面向对象的范型中,通常在运行时才能知道给定消息的特定的接收者。

7.关系机制

        关系机制为我们提供了用同等(关联、依赖)和层次(一般化/特殊化和聚合)结构组织类/对象的方法。很多面向对象的专家把模型的这部分结构称作静态模型。我们使用James Martin和James Odell的术语,将其称为结构分析。然而,一个应用/系统有了结构分析并不充分,还需要进行行为分析。行为分析是我们用来考察一个对象(类)是怎样提供它的操作的过程。 从分析的视点,有两种类型的行为:

静态的:在静态行为中,实现操作的代码不被任何外部或内部的事件(动作)所影响。

动态的:在行为中发生这些变化的原因可能是由于对象存在很多不同的状态。随后,对象根据它的状态做出反映。使用命令式编程技术不能很好地处理这种类型的行为。使用另外的一种称为有限状态机的机制会更好地捕获这样的方法。 

8.复杂性控制

        引入包(package) 的概念,使模型具有大小不同的粒度层次,以利于控制复杂性。 如把分析和设计阶段的模型分别用包进行组织。

面向对象的分析与设计:

        OOA(分析):

        面向对象的分析(Object Oriented Analysis, OOA),就是运用面向对象方法进行系统分析。其基本任务即运用面向对象方法,对问题域和系统责任进行分析和理解,找出描述问题域及系统责任所需的对象,定义对象的属性、操作以及它们之间的关系。其目标是建立一个符合问题域、满足用户需求的OOA模型。

        OOA是分析,是软件生命周期的一个阶段,具有一般分析方法共同具有的内容、目标及策略;强调运用面向对象方法进行分析,用面向对象的概念和表示法表达分析结果。

 问题域(problem domain):被开发系统的应用领域,即在现实世界中由这个系统进行处理的业务范围。

系统责任(system responsibilities):所开发的系统应该具备的职能。

        OOD(设计):

        从OOA到OOD不是转换,是调整和增补。使OOA作为OOD模型的问题域部分;增补其它四个部分,成为完整的OOD模型。

        OOA主要针对问题域,识别有关的对象以及它们之间的关系,产生一个映射问题域,满足用户需求,独立于实现的OOA模型。

        OOD主要解决与实现有关的问题,基于OOA模型,针对具体的软、硬件条件(如机器、网络、OS、GUI、DBMS等)产生一个可实现的OOD模型。

Java与面向对象:

        对象是 Java 程序的核心,在 Java 程序中“万事万物皆对象”。 

        对象可以看成是静态属性(成员变量)和动态属性(方法)的封装体。类是用来创建同一类型的“模板”,在一个类中定义了该类对象所具有的成员变量以及方法 

Java 语言中除基本类型之外的变量类型都称为引用类型 
Java 中的对象是通过引用对其操作的。 
例如: 

Dog dog; 
dog = new Dog(); 

        对象是 new 出来的,位于堆内存,类的每个成员变量在不同的对象中都有不同的值 (除了静态变量)而方法只有一份,执行的时候才占用内存。 

类中成员变量的定义与意义:

        在Java中对象的属性(静态部分)也称为成员变量。

        成员变量可以使用 Java 语言中任何一种数据类型(包括基本类型和引用类型)

        定义成员变量时可以对其初始化,如果不对其初始化,Java 使用默认的值对其初始化。

成员变量类型取值
byte0
short0
int0
long0L
char'\u000'
float0.0F
double0.0D
booleanfalse
所有引用类型null

构造方法的定义和调用:

        定义:

        构造方法的名字必须和所在类的名字一致,没有返回值,但不能声明void,访问权限可以为任意,但是一般情况下使用public方法权限,构造方法中的参数可以根据需要自行定义,参数的不同的构造方法构成重载;

        构造方法的使用:

        java中构造方法的使用有两个地方,一个是跟在关键字new后面,类名加上一个小括号(),小括号内根据实际加上实参,另外一个是跟在关键字super或this后加上一个小括号(),小括号内根据实际添加实参,下面进行举例。

        构造方法的作用:

  • 为了初始化成员属性,而不是初始化对象,初始化对象是通过new关键字实现的
  •  通过new调用构造方法初始化对象,编译时根据参数签名来检查构造函数,称为静态联编和编译多态
  •  (参数签名:参数的类型,参数个数和参数顺序)                                                                        创建子类对象会调用父类构造方法但不会创建父类对象,只是调用父类构造方法初始化父类成员属性;

LintCode刷题:

·位运算左移三位

        使用<<符号即可,移位是在二进制上的移位 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        int n =scanner.nextInt();
        System.out.println(n<<3);
    }
}

··圆形周长

        使用到Math中的Pi常量即可 

public class Main {
    public static void main(String[] args) {
        int r = Integer.parseInt(args[0]);
        System.out.printf("%.2f\n", Math.PI * 2 * r);
    }
}

·最大二叉树

 

         使用方法的递归来创建左子树和右子树,首先要找出根节点,只需要找出数组中最大的数即可,把它当作根节点然后再由方法的递归来实现树结构

public class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        if (nums == null)
            return null;
        return build(nums, 0, nums.length - 1);
    }

    public TreeNode build(int[] nums, int start, int end) {
        if (start > end)
            return null;
        int index = start;
        for (int i = start + 1; i <= end; i++) {
            if (nums[index] < nums[i])
                index = i;
        }
        TreeNode root = new TreeNode(nums[index]);
        root.left = build(nums, start, index - 1);
        root.right = build(nums, index + 1, end);
        return root;
    }
}

· 最后一个单词的长度

         1.用sqlit来分割出来,返回最后一个即可

public class Solution {
    public int lengthOfLastWord(String s) {
        s=s.trim();
        String[] arr =s.split(" ");
        return arr[arr.length-1].length();
    }
}

        2. 去掉头尾的空格后直接从后遍历字符串,每次使count++,然后遍历到空格返回count即可

public class Solution {

    public int lengthOfLastWord(String s) {
        int count =0;
        boolean index = false;
        s=s.trim();
        for (int i =s.length()-1;i>=0;i--){
            if (s.charAt(i)!=' '){
                count++;
            }
            if (s.charAt(i)==' '){
                break;
            }
        }
        return count;
    }

    public static void main(String[] args) {
        Solution solution =new Solution();
        int i = solution.lengthOfLastWord("Hello World");
        System.out.println(i);
    }
}

·判断连接 

         创建一个可以一直递归的方法,可以一直进行数值相同的移动。

public class Solution {
    public boolean judgeConnection(int[][] arr, int k) {
        int sum =0;
        for (int i =0;i<arr.length;i++){
            for (int j =0;j<arr[0].length;j++){
                if (arr[i][j]==k){
                    Connection(arr,i,j,k);
                    sum++;
                    if (sum>=2)
                        return false;
                }
            }
        }
        return true;
    }
    public void Connection(int[][] arr,int i,int j,int k){
        arr[i][j]=-1;
        int di[] = {0, 0, 1, -1};
        int dj[] = {1, -1, 0, 0};
        for (int z =0;z<4;z++) {
            int i1 = i + di[z];
            int j1 = j + dj[z];
            if (i1>=0&&j1>=0&&i1<arr.length&&j1<arr[0].length&&arr[i1][j1]==k)
                Connection(arr,i1,j1,k);
        }
    }
}

 ·乱序字符串

         主要需要注意两个问题,chars的toString方法不可以输出空的字符串(""),第一个乱序字符串是不会在第一次碰到就可以加入,得在第二次遇到时,才能把上一个加入,再加入本次这个

        运用Map来记录上一次传入的位置,首先定义一个方法,把这个字符串转成字符数组,排序后返回,得使用return new String,这样遇到空("")才可以把空("")返回,遍历字符串数组,在map中不含有这个字符串时,先把这个i的位置转换成负数put进去,然后第二次碰到同个字符串的时候就可以,根据对应的value值是否大于0,来判断前一个是不是第一次出现的,是就先将他放入需返回的List里面,再将这此遍历的字符串也放入需返回的List里面,再将这次的i值put进入map里面,让这个str对应的value值不再是负数。

import java.util.*;

public class Solution {
    List<String> stringList=new ArrayList<>();
    Map<String,Integer>stringIntegerMap=new HashMap<>();
    public List<String> anagrams(String[] strs) {
        if (strs==null||strs.length==0){
            return stringList;
        }
        for (int i =0;i<strs.length;i++){
            String str = sortString(strs[i]);
            if (!stringIntegerMap.containsKey(str)){
                stringIntegerMap.put(str,-i-1);
            }else {
                int index = stringIntegerMap.get(str);
                if (index<0) {
                    stringList.add(strs[-index - 1]);
                }
                stringList.add(strs[i]);
                stringIntegerMap.put(str,i);
            }
        }
        return stringList;
    }
    public String sortString(String str){
        char[] chars =str.toCharArray();
        Arrays.sort(chars);
        return new String(chars);
    }
}

学习时间:

2021/9/6 9:00-11:45、13:30-17:30


学习产出:

学习博客*1

刷题*6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值