面试的时候面试官可能会问到这个问题:不引入类怎么创建这个类的对象和执行类的方法 想必大家都知道Runtime 。到底Runtime是怎么创建的呢,下面是一个小demo。...All rights reserved. // /* 利用Runtime不引用头文件, 动态创建类对象,并调用方法 */ #import "ViewController.h" #import...翻译成Runtime动态加载语言 */ Person * person = [[Person alloc]init]; /* 1.objc_msgSend 给Person类发消息让他调用...OBJC_AVAILABLE(10.0, 2.0, 9.0, 1.0); 2.objc_getClass 返回这个类的isa指针 OBJC_EXPORT Class objc_getClass...@selector(alloc) 方法选择器,同样可以通过sel_registerName注册方法名 @selector(alloc)==sel_registerName("alloc") */
我们知道 Kotlin 的 data class 出厂自带了一套 copy 方法,这个 copy 方法呢,就是实打实的一个浅拷贝,例如: data class GitUser(val name: String...所以,你需要为每一个数据类定制一个 deepCopy 方法。。。 来来来,先实现个简单的 天哪。那岂不是要写死了。...用反射再配合 Kotlin 最优秀的特性之一的扩展方法,我们就可以为所有的类无缝提供一个 deepCopy 的扩展方法,当然,我们的目标是为数据类服务,所以其他类调用这个方法我们一概直接返回(~ ̄▽ ̄)...~ fun T.deepCopy(): T { //①判断是否为数据类,不是的话直接返回 if (!...copy 很像了,不同之处就是我们会递归的检查哪些数据类被标注为 DeepCopy,如果标注,就递归调用对应的 deepCopy 函数。
类属性只能通过方法来修改,由于子类会引入父类中不存在的方法,方法的引入可能会导致原来在父类中不可修改的属性在子类中可以修改了,历史约束禁止这种行为。...子类在继承后,固然是获得了超类的带来的‘财富’,更重要的是要遵守超类做出的承诺, 破坏了这个承诺实际上是没有资格继承超类的。 如果破坏了继承原则,那么开闭原则也就无法使用。...this.name = name; } public void fly() { System.out.println(name + " fly"); } } 大部分鸟在这个基类中都工作的很好...注意,这里已经违反了 LSP 原则,在基类中并没有异常抛出,使用方正常使用,而在 Penguin 类中 fly 方法抛出了异常,违反了基类遵守的契约。...,有时我们可能在无意中就已经违反了原则要求,一是因为我们没有意识到,二是我们设计的接口、抽象基类有问题。
里氏替换原则的内容可以描述为: “派生类(子类)对象可以在程序中代替其基类(超类)对象。” 以上内容并非利斯科夫的原文,而是译自罗伯特·马丁(Robert Martin)对原文的解读。...简单来说,子类可以扩展父类的功能,但不能改变父类原有的功能,也就是说,在子类继承父类时,除添加新的方法且完成新增功能外,尽量不要重写父类的方法。...这种继承父类的优点是复用了父类的核心功能逻辑,但是也破坏了原有的方法,此时也破坏了原有的方法。...四、里氏替换原则改变代码 哪吒和敖丙都有称号、师傅、混元珠,在《封神榜》中也有很多共同特点和经历,实现这样的类的最好方式是提取出一个抽象类,由抽象类定义所有人物的共同核心属性、逻辑。...1、抽象人物类 在抽象类银行卡类中,提供了人物的基本信息,包括id、姓名,姓名、武力值以及三个基本的方法。接下来继承这个实现类,实现哪吒和敖丙的技能逻辑。
一个元素的变动,都需要我们花费大量的代价去维护我们的代码,所以说这时候我们就要引入PO模式来解决这个问题。 第二,什么是PO模式? ...,方法名最好根据对应的业务场景进行命名。...先来看下代码的目录结构: Page目录下存放的是页面对象,BasePage是基类,我们页面对象需要继承基类。...先看基类的代码: 基类主要是将selenium的元素操作进行了再次封装,方便我们的调用。...在python中,如果是在函数调用中,* args表示将可迭代对象扩展为方法的参数列表;如果是函数定义中参数前的*表示的是将调用时的多个参数放入元组中; 这里是重点,因为如果这里没写好,就会报错。
抽象(Abstraction)和多态(Polymorphism)是实现这一原则的主要机制,而继承(Inheritance)则是实现抽象和多态的主要方法。 那么是什么设计规则在保证对继承的使用呢?...它必须知道所有 Shape 基类的衍生子类,并且当有新的子类被创建时就必须修改这个函数。事实上,很多人看到这个函数的结构都认为是在诅咒面向对象设计。...而失败的原因是因为在父类 Rectangle 中没有将 SetWidth 和 SetHeight 设置为 virtual 函数。 我们也能很容易的解决这个问题。...但当我们从一个对基类做出合理假设的程序员的角度来看待它们时,这个模型就被打破了。...前置条件为真,则方法才能被执行。而在方法调用完成之前,方法本身将确保后置条件也成立。
基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。...(在子类成员函数中,可以使用 基类::基类成员 显示访问) 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。 注意在实际中在继承体系里面最好不要定义同名的成员。...复杂的菱形继承及菱形虚拟继承 单继承:一个子类只有一个直接父类时称这个继承关系为单继承 多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承 菱形继承:菱形继承是多继承的一种特殊情况...术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。...菱形继承的问题是什么? (1)菱形继承是指在类的继承关系中,存在两个或更多个直接或间接的基类,它们之间形成了一个类似菱形的结构。
基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在 派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。 3....二、基类和派生类对象赋值转换 我们首先要知道凡是类型转换,中间都会产生临时变量,注意这个临时变量是一个常量!!! 因此下面的代码是有语法错误的。...因为这里的i在给r赋值时会产生临时变量,而这个临时变量是一个常量,而r是一个变量,所以这里的r前面要加上const,变成常量。 接着,那基类和派生类对象赋值转换是什么意思呢?...七、复杂的菱形继承及菱形虚拟继承 单继承:一个子类只有一个直接父类时称这个继承关系为单继承 多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承 菱形继承:菱形继承是多继承的一种特殊情况。...术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
内联函数,都知道是什么嘛,就不多解释了,用这个开头,因为它够简单,又有足够的争议性。...返回引用时,应避免返回函数终止时不再存在的内存单元引用(在指针里说过同样的话)。 为避免这种问题,最简单的方法就是:返回一个作为参数传递给函数的引用。 ---- 何时使用引用参数? 想用的时候呗。...虚函数表中存储了为对象进行声明的虚函数的地址。 例如,基类对象包含一个指针,该指针指向基类中所有虚函数的地址表。派生类对象包含一个指向独立地址表的指针。...至于它是否破坏了类的封装性,这个不同的人有不同的说法啦,认为它没有破坏封装性的人觉得只有类声明可以控制哪些函数可以访问内部数据。...非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。
,需要改写这个方法的可能性就很大。...从前,一个人负责两个不同的任务,为任务1,任务2,当任务1需要做调整时,而需要这个人做修整时,有可能会影响任务2的正常运行,会导致任务2没有办法完成。...里氏替换原则:所有引用基类的地方必须能够使用其子类的对象,从前有一个游戏玩家A,它有一个招式Z1,现在把这个招式Z1进行扩展,扩展后成为大招Z,其大招Z由原来的招式Z1和新功能Z2组成,新功能Z又由游戏玩家...父类变,子类必须变;继承破坏了封装(子类是封装的,因父类的改变,导致父类破坏了子类的封装),对于子类来说,通过继承父类,是没有安全保障的,父类修改其内容,就会导致子类的功能被破坏;对于父类来说,子类继承父类...,但是这个接口有它不要的方法,就需要把这个接口拆分,把它需要的方法独立出来形成一个新的接口给这个类去实现。
如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。这就像契约模式,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。...如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。 Java8中的默认方法和静态方法 Oracle已经开始尝试向接口中引入默认方法和静态方法,以此来减少抽象类和接口之间的差异。...接口使用原则S.O.L.I.D原则 单一职责(Single Responsibility),类或者对象最好是只有单一职责,在程序设计中如果发现某个类承担着多种义务,可以考虑进行拆分。...里氏替换(Liskov Substitution),这是面向对象的基本要素之一,进行继承关系抽象时,凡是可以用父类或者基类的地方,都可以用子类替换。...接口分离(Interface Segregation),我们在进行类和接口设计时,如果在一个接口里定义了太多方法,其子类很可能面临两难,就是只有部分方法对它是有意义的,这就破坏了程序的内聚性。
在student中,就不需要重定义,省去了许多麻烦 1.2.1继承方法 继承方法,是通过不同的继承方法,可以指定基类的成员继承到派生类中后的访问方式,是pbulic公共的成员、还是private私有的成员...最好用的做法是使用auto关键字,自动推导类型。...在派生类中显示调用基类的同名函数 四.派生类的默认成员函数 4.1默认成员函数的行为 默认成员函数的两个主要问题: 不写默认成员函数,编译器默认生成的行为是什么 默认生成的成员函数不符合需求,自己该如何实现...通过这种生成派生类的复用常被称为白箱复用 白箱,相对可见性而言,基类的内部细节对派生类可见,继承一定程度上破坏了基类的封装,基类的该变会对继承产生很大的影响 派生类和基类之间依赖关系强,耦合度很高...模块内部功能不聚焦,会出现重复的代码来处理不同的功能部分 程度上破坏了基类的封装,基类的该变会对继承产生很大的影响 派生类和基类之间依赖关系强,耦合度很高 对象组合是类继承的另一种复用选择。
菱形继承的问题是什么? 菱形继承:菱形继承是多继承一种特殊的继承方式。如下如所示为一菱形继承 ? 即两个派生类继承同一个基类,同时两个派生类又作为基本继承给同一个派生类。...菱形继承的问题:菱形继承主要有数据冗余和二义性的问题。由于最底层的派生类继承了两个基类,同时这两个基类有继承的是一个基类,故而会造成最顶部基类的两次调用,会造成数据冗余及二义性问题。...下图是菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。...继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。 对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。...4.c++之哪些成员函数不能被继承 构造函数:在创建子类对象时,为了初始化从父类继承来的数据成员,系统需要调用其父类的构造方法。
问题二十二: 你听过虚基类吧,虚基类的作用是什么,虚基类的实现机制就是什么呢?...答: 虚基类的作用是在C++多重继承的情况下,如果出现菱形继承的话,为了消除 在子类中出现父类数据实体的多份拷贝。 虚基类的实现机制这个有点复杂。不同编译器内部实现的机制也不相同。...其主要有两种实现方案: (1)是引入virtual base class table,不管多少个虚基类,总是只有一个指针指向它,这个virtual base class table(VBTBL)包括真正的...在VC++中,采用的是类似第一种方案。对每个继承自虚基类的类实例,将增加一个隐藏的“虚基类表指针”(vbptr)成员变量,从而达到间接计算虚基类位置的目的。...但是当子类没有虚函数表指针时,编译器会为子类对象生成一个指针变量,这个指针变量很可能就是指向虚基类表。
大量访问方法意味着相关数据和行为没有集中存放。 (15)对包含太多互不沟通的行为的类多加小心。 这个问题的另一表现是在你的应用程序中的类的公有接口中创建了很多的get和set函数。 ...质疑任何名字是动词或者派生自动词的类,特别是只有一个有意义行为的类。考虑一下那个有意义的行为是否应当迁移到已经存在或者尚未发现的某个类中。 (21)我们在创建应用程序的分析模型时常常引入代理类。...(45)如果两个或更多个类有共同的数据和行为(就是方法),那么这些类的每一个都应当从一个表示了这些数据和方法的公共基类继承。 ...(49)不要通过继承关系来为类的动态语义建模。试图用静态语义关系来为动态语义建模会导致在运行时切换类型。 (50)不要把类的对象变成派生类。对任何只有一个实例的派生类都要多加小心。 ...(52)在派生类中用空方法(也就是什么也不做的方法)来覆写基类中的方法应当是非法的。 (53)不要把可选包含同对继承的需要相混淆。把可选包含建模成继承会带来泛滥成灾的类。
这得追溯到遥远的过去,当时的程序员们发现,许多类的属性和方法都是相似的,于是他们想出了一个绝妙的主意:为什么不把这些相似的部分提取出来,形成一个"父类",而其他的类则通过"继承"这个父类来获得这些属性和方法呢...派生类无法直接访问基类的私有成员(可以间接访问),类外也无法访问。 如果基类的成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。...通过继承的特性,基类一般都定义为public 和 protected,不使用private。...(在子类成员函数中,可以使用 基类::基类成员 显示访问) 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。 注意在实际中在继承体系里面最好不要定义同名的成员。...术语 “白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
,他们都是人,都有一些人的基本信息,比如上图红框中的姓名和年龄,如果每个类都定义上年龄和姓名的话,代码会非常冗余,而且如果以后想要在基本信息中加上一些信息时,我们需要把每个类都添加一遍,这个时候我们的继承就该登场了...基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在 派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。 3....随着c++的更新迭代,官方终于给出了解决方法:那就是在继承公共基类时使用虚拟继承(virtual) 这样就可以正常访问了 继承和组合: 1.public继承是一种is-a的关系。...4.继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称 5.为白箱复用(white-box reuse)。...术语“白箱”是相对可视性而言:在继承方式中,基类的 内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很 大的影响。派生类和基类间的依赖关系很强,耦合度高。
如果要理解为:一个类只有一个职责,当然也是可以的,简单化嘛。...void 挂电话(); }; 这个有没有问题?是有那么小问题的嘞。 你说我哪天,拨号的方法要改一下,我变成拨不通就一直拨,那这个类变一下。...然后我通信的方法再改一下,我现在不允许两个人同时说话,一个说完另一个再说,那这个类再变一下。 这个类,有两个职责:协议管理和数据传送。 那怎么搞?...所有引用基类的地方,必须能透明的使用其子类对象。 什么意思呢?就是子类必须实现父类的所有方法。有父类出现的地方,子类就可以出现。...只要通过以下的几个规则: 每个类尽量都有接口或抽象类,或者抽象和接口二者都具备。 变量的表面类型尽量是接口或者抽象类。 任何类都不应该从具体类派生。 尽量不要覆写基类的方法。 结合里氏替换原则。
如果要理解为:一个类只有一个职责,当然也是可以的,简单化嘛。...void 挂电话(); }; 这个有没有问题?是有那么小问题的嘞。 你说我哪天,拨号的方法要改一下,我变成拨不通就一直拨,那这个类变一下。...所有引用基类的地方,必须能透明的使用其子类对象。 什么意思呢?就是子类必须实现父类的所有方法。有父类出现的地方,子类就可以出现。...只要通过以下的几个规则: 每个类尽量都有接口或抽象类,或者抽象和接口二者都具备。 变量的表面类型尽量是接口或者抽象类。 任何类都不应该从具体类派生。 尽量不要覆写基类的方法。 结合里氏替换原则。...有如下方法: 1、修改接口 2、修改实现类 3、通过拓展实现变化 至于为什么需要这个原则、如何使用、何时使用这个原则,跟着我的步伐,往后看。
(在派生类成员函数中,可以使用基类::基类成员显示访问。) 3.对于成员函数的隐藏,只需要函数名相同就行了。 4.实际上在继承体系中最好不要定义同名的成员。...//这个派生类对象包含的基类对象跟直接用基类实例化出的对象是不一样的 cout << &p._name << endl; cout << &s...._count << endl; return 0; } 多继承 单继承:一个派生类只继承了一个基类时,这个继承关系叫做单继承。 多继承:一个派生类继承了多个基类时,这个继承关系叫做多继承。...虚基表存有两个数据,一个是为多态的虚表准备存偏移量的位置,第二个就是当前类对象距离公共虚基类的偏移量,通过虚基表指针找到虚基表,通过虚基表中的偏移量找到公共虚基类。...术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
领取专属 10元无门槛券
手把手带您无忧上云