-
Java 静态内部类的方法如何获取
2020-10-19 17:47:07原来,在a类中还有一个静态内部类,他是把字段加到这个静态内部类中,因此不能在别的类中被get到。 改对位置后,则能get到值了: 涉及知识点 这里主要涉及到对内部类的认识,尤其是静态内部类。 public ...场景
今天碰到一个极为经典的问题,是同事在开发期间碰到的。问题大概描述如下:
在a类中添加了一个字段,同时也利用lombok声明了其set和get方法。但是在b类中怎么也get不到这个字段。
我在仔细看了之后,发现原因很简单,同事是把字段加错位置了。原来,在a类中还有一个静态内部类,他是把字段加到这个静态内部类中,因此不能在别的类中被get到。
改对位置后,则能get到值了:
涉及知识点
这里主要涉及到对内部类的认识,尤其是静态内部类。
public class InnerClass { private static String nickName = "anan"; private String name; private int age; public InnerClass(String name, int age) { this.name = name; this.age = 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; } public static class Inner { private String heart = "zhaoli"; public String getHeart() { return heart; } public void setHeart(String h) { this.heart = h; } public void print() { System.out.println(InnerClass.nickName); System.out.println(getHeart()); } } }
我们可以写一个测试类:
public class InnerClassTest { public static void main(String[] args) { InnerClass.Inner inner = new InnerClass.Inner(); inner.print(); inner.setHeart("simple-simply"); inner.print(); } }
这个就是从静态内部类中调用方法的方式。
后续再整理静态内部类在开发过程中的优缺点。
-
java抽象方法实例_java抽象方法怎么操作?实例代码分享
2021-02-28 14:56:48首先说一下,如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名...随时代的不断进步与发展,学习java的人也是越来越多,大家都希望通过它来获得更好的生活水平。java中的知识点是非常繁多的,而且涉及的方面也是非常广阔的。一起来了解一下吧。
首先说一下,如果你想设计这样一个类,该类包含一个特别的成员方法,该方法的具体实现由它的子类确定,那么你可以在父类中声明该方法为抽象方法。abstract关键字同样可以用来声明抽象方法,抽象方法只包含一个方法名,而没有方法体。
同样需要注意的是,抽象方法没有定义,方法名后面直接跟一个分号,而不是花括号。代码如下所示:public abstract class Employee
{
private String name;
private String address;
private int number;
public abstract double computePay();
//其余代码
}
另外,声明抽象方法会造成以下两个结果:
1.如果一个类包含抽象方法,那么该类必须是抽象类。
2.任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
继承抽象方法的子类必须重写该方法。否则,该子类也必须声明为抽象类。最终,必须有子类实现该抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
如果Salary类继承了Employee类,那么它必须实现computePay()方法,代码如下所示:/* 文件名 : Salary.java */
public class Salary extends Employee
{
private double salary; // Annual salary
public double computePay()
{
System.out.println("Computing salary pay for " + getName());
return salary / 52;
}
//其余代码
}
为大家总结一下抽象类的主要规定:
⑴ 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
⑵抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
⑶抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
⑷构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
⑸抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
以上就是关于java抽象方法怎么操作的主要内容了,并且用实际的代码为大家分享出来了。具体的内容还是比较详细的。如果你想要了解更多java实例,敬请关注奇Q工具网。
推荐阅读:
-
Java中封装、继承和多态的特性你了解多少?
2020-07-02 13:53:18至于属性和方法具体怎么声明和定义,继承后子类和父类的关系具体又是怎样的,就云里雾里了。 本文会尽量用最通俗易懂的语言来描述面向对象中的三大特性,这个东西比较抽象,学会的话就觉得在码代码的时候用起来特别...一谈到Java肯定就要谈到面向对象,万物皆对象是每个Java学习者都听了不知道多少遍的话,然而很多刚学编程的人学到这里会一脸懵逼,就算跟着教程一步一步敲代码了,也就知道建个类要加class关键字,也知道类有属性和方法,也知道继承用extends关键字。至于属性和方法具体怎么声明和定义,继承后子类和父类的关系具体又是怎样的,就云里雾里了。
本文会尽量用最通俗易懂的语言来描述面向对象中的三大特性,这个东西比较抽象,学会的话就觉得在码代码的时候用起来特别方便,不会的话就会觉得太难了。任何一本Java书籍或者视频在讲到面向对象这一块的时候,都会花比较多的篇幅来讲解,本文也达不到将所有知识点全部讲出来,因为其中的细节确实挺多,而新手懵也就懵在了这么多细节上了。不过,最开始学习的时候你只需要掌握平常的基本使用就可以,至于其他细节在使用的过程中就会慢慢学会!
思路
了解一个东西怎么使用其实不难,就好像你要去了解一个杯子具体是怎样生产的和背后生产的原理,你肯定要懵,但是只让你拿一个杯子去装水却轻而易举,你在使用的过程中完全不需要关心杯子的细节,你只需要会用就行。
而很多人问题就出在这里,大部分人是“杯子”是什么都没弄清楚,脑袋里就压根没“杯子”这个概念,就更不用谈去使用“杯子”了。 所以,本文的重点就是让大家理清面向对象中 封装、继承和多态 这三个概念,代码会贴的比较少。让大家知道“杯子”大概是怎么就行了,后续的使用过程中会掌握更多细节的。
在讲解具体的概念之前,要和大家强调一点: 面向对象是为了方便我们构建代码,并不是增加我们构建代码的难度!!! 面向对象是为了方便我们构建代码,并不是增加我们构建代码的难度!!! 面向对象是为了方便我们构建代码,并不是增加我们构建代码的难度!!!
一定要以,啊我多了一个特别好用的工具,这种思维来去学习,而不是以,啊我多了一个负担这种思维
封装
封装只是一种概念,也是面向对象非常重要的一个特性。
其实封装在我们生活中无处不在,在平常构建代码的过程中也经常用到封装,封装就是隐藏细节: 你到银行取钱你只需提供银行卡和密码,柜员会将卡里的钱给你,至于柜员是在柜台后面如何验证你的密码、余额,又是如何从金库里拿到现金再给你,你都不知道也无需知道,这就是封装。银行封装了柜员在柜台后面操作的细节 再比如你到餐厅里去吃饭,你点好菜之后只需要等待服务员将菜端上给你,而不知道这个菜是如何做好的,这也是封装。餐厅封装了厨师在厨房里做菜的细节。
生活中封装的例子随处可见,在程序中封装也无处不在: 你调用Java库中的某个方法来实现某个功能,你只需要传入正确的参数即可让方法运行达到你想要的目的,至于方法内部进行了怎样的操作,具体是怎样完成这个功能的你都不知道也无需知道。方法封装了方法内部的细节。 你使用某个类的实例,你创建出一个对象,你如愿以偿拿到了对象的引用,但是这个对象具体是怎样构造出来的你不知道,构造函数里的细节你不清楚,你也不会知道有哪些私有数据,要操作这个对象一律得通过提供的方法来调用。构造函数封装了对象初始化流程。private封装了对象的私有数据成员
所以封装的主要目的就是隐藏细节,将对象当做黑箱进行操作。
继承
面向对象中子类继承父类,主要是为了避免重复的行为定义,比如Animal类你定义了 体重、年龄等多个属性,又有 吃东西、玩等多个行为,然后你又想弄出一个Dog类,你会发现Dog类我要定义的属性和行为Animal类都有,那我就无需再重新定义一遍了,直接将Dog类继承Animal类,就会让Dog类拥有Animal类的属性和行为。
不过并非为了避免重复定义行为就要使用继承,滥用继承而导致程序维护上的问题时有耳闻。如何正确判断使用继承的时机,以及继承之后如何活用多态,才是学习继承的重点。而这些在我们没有理清继承的概念之前是无法做到的。
理清继承的概念,可以简单使用 “is-a”来判断子类和父类的关系,中文称为“是一种”的关系。简单来说,如果你可以这样描述:B是一种A,那么B继承了A。能通过“is-a”测试,在逻辑上和程序中就能顺利使用继承关系
比如现在Dog类和Cat类继承了Animal类:
/*创建两个对象,这肯定没问题*/ Dog dog = new Dog(); Cat cat = new Cat(); /*这两句也可以通过编译*/ Animal animal1 = new Dog(); // Dog是一种Animal Animal animal2 = new Cat(); // Cat是一种Animal /*但是下面两句就无法通过编译*/ Dog dog = new Animal(); // Animal不一定是Dog,所以编译失败 Cat cat = new Animal(); // Animal不一定是Cat,所以编译失败 复制代码
前两段代码通过了“is-a”测试,自然是没什么问题,而第三段代码就没有通过“is-a”测试,所以自然编译失败。编译器就是语法检查器,检查的方式是从 = 号右边往左读:右边是不是一种左边呢(右边类是不是左边类的子类)?
上面代码不管是从逻辑上还是程序上都好理解,我们来看下面的代码:
Animal animal = new Dog(); // Dog是一种Animal,这一行可以通过编译 Dog dog = animal; // 这一句话编译失败 复制代码
第一行没话说,都知道能通过编译,那么第二行是为啥编译失败呢? 编译器检查语法一次只看一行,它又无法联系上下文来做阅读理解,animal你是用Animal类来做声明的,自然而然编译器将就你认定为Aniaml类,尽管你指向的是子类Dog,但是animal现在的“身份”还是Aniaml类。所以,第二行无法通过“is-a”测试,编译失败。
编译器会检查父子类之间“is-a”关系,如果你不想要编译器啰嗦可以叫它住嘴:
Animal animal = new Dog(); Dog dog = (Dog)animal; 复制代码
对于第二行本来编译器是要提示你,animal不一定是Dog类的对象哦,但是你加上强制类型转换让它住嘴了,编译器就让这段代码通过编译了,不过后果得自行负责
就上面这个代码来说,animal确实指向了Dog类实例,所以第二行让Dog实例转换成Dog并没有什么问题,执行期间也不会出错。但是下面代码可以通过编译,但是运行时却会报错:
Animal animal = new Dog(); Cat cat = (Cat)animal; 复制代码
你让编译器闭嘴了,编译器让你通过了编译,不过在运行时发现animal明明是指向的Dog类,你让Dog转换成Cat那肯定是不行的!因为Dog并不是一种Cat。
综上所述,使用“is-a”原则就可以判断何时编译成功,何时编译失败,并留意指向的实例类型,就可以判断何时扮演成功,何时会抛出异常! 然后在要使用继承前,也可以在逻辑上判断是否该使用继承: 狗是动物吗?是的,所以狗继承动物没有一点问题。猫是动物吗?是的,所以猫继承动物也没有一点问题。树是一种动物吗?不是,这在逻辑上说不过去,所以在程序中也不应该让树继承动物类,否则会导致程序的整体逻辑混乱。 在程序中,并没有任何限制可以防止你不继承某个类,你当然可以让Tree extends Animal,但是这样是完全不合理的,作为开发者应当避免这种乱继承的行为!
上面这个例子还非常好判断,但是将来开发的过程中各种类的关系错综复杂,就需要好好理清“is-a”关系了。 比如 酒店浴室是一种浴室吗?是的,那让酒店浴室类继承浴室没有问题。家用浴室是一种浴室吗?是滴,让家用浴室继承浴室类也没有问题。 那么,浴盆是一种浴室吗? 好像挺有关系的,不过稍微一琢磨倒也能理清,浴盆与其说 is a 浴室,倒不如说 浴室 has a 浴盆,这就牵扯到另一个原则了 “has-a” 原则,中文来说就是 “有某个”东西。 浴室里可以有浴盆,所以浴盆应当是浴室的一种属性,而不是一种子类。所以将浴盆定义成浴室的属性就要比浴盆继承浴室要好很多!
理清继承,用最简单的办法就是: “is-a”原则帮助你判断父子类的关系,“has-a”原则帮助你判断类与成员的关系!
多态
多态,即多种形态或者多种状态。听起来挺深奥,其实非常简单,多态在生活中也无处不在: 假设你现在开了一个宠物店,提供给宠物洗澡的服务,于是你吩咐店员贴一个公告,咱们店可以给所有哈士奇洗澡!于是附近的居民都带着哈士奇过来洗澡了,你高兴的不得了,因为赚了钱。 这个用程序的语言来描述就像你这个宠物店给大家提供了一个方法:
// 参数是哈士奇类,执行的功能洗澡 public static void shower(哈士奇 h); 复制代码
但是好像有一个问题,有居民带着一个金毛过来准备给金毛洗澡,但是店员不允许金毛过来洗,因为你吩咐的就是让哈士奇洗,金毛并不是哈士奇,所以不行。 又有其它居民带着萨摩耶、柴犬啥的过来,店员都把他们拒之门外了,更有甚者还有人带着猫过来,那就更不用多说了,不准洗。 你失去了很多顾客,但是你还没办法生气,因为店员尽责得执行了你下达的指令:
shower(哈士奇类的对象); // 通过,因为传进来的参数是匹配的 shower(金毛类的对象); // 报错,因为传进来的参数类型不是哈士奇 shower(萨摩耶类的对象); // 报错,因为传进来的参数类型不是哈士奇 shower(猫类的对象); // 报错,因为传进来的参数类型不是哈士奇 复制代码
你发现自己好像做了一件傻事,自己明明是个宠物店却只限制让哈士奇过来洗澡,那自然生意就限制了很多很多。于是乎你决定让各种各样的宠物都可以过来洗澡,哈士奇,金毛也行,萨摩耶也行:
public static void shower(哈士奇 a); // 参数是哈士奇类,执行的功能洗澡 public static void shower(金毛 a); // 参数是金毛类,执行的功能洗澡 public static void shower(萨摩耶 a); // 参数是萨摩耶类,执行的功能洗澡 public static void shower(猫 a); // 参数是猫类,执行的功能洗澡 ... ... ... 复制代码
你定义了一万个方法,因为宠物品种实在是太多了,你必须要考虑到各种各样的品种。然而你发现,这样成本太高了也太麻烦了,问题虽然能够解决但是却让你精疲力尽。o(╥﹏╥)o
于是你决定改变,你重新吩咐店员,只要是宠物(或动物)就都可以过来享受洗澡服务!这个指令一下达,生意立马就好了,O(∩_∩)O~ 因为别人不管是带着哈士奇过来还是金毛、萨摩耶或者猫过来,都可以。用程序描述就是:
// 参数是宠物(动物)类,执行的功能是洗澡 public static void shower(Aniaml a); public static void main(String[] args) { shower(哈士奇类的对象); // 通过,哈士奇类继承了Animal类 shower(金毛类的对象); // 通过,金毛类继承了Animal类 shower(萨摩耶类的对象); // 通过,萨摩耶类继承了Animal类 shower(猫类的对象); // 通过,猫类继承了Animal类 } 复制代码
这就是多态的一种表现,你明明只限定了一个参数类型,但是传进来的参数却各种形态都有。 是不是方便到爆了?
而通过上述例子咱们也可以发现多态的达成条件: 要有继承 父类引用指向子类对象
你参数定义的是Animal类,传进来的参数虽然可以多种多样,但是也不能瞎传参数进来,得是继承了Animal类的子类才可以。 然后呢,参数类型是父类,传进来的却是子类,在方法里面我操作的实例也是子类对象,这就是前面我们演示“is-a”原则时所体现出来的:父类的引用指向子类的对象。
这个理解后,咱们再来深入一些: 你现在宠物店决定拓展业务了,不光要能提供洗澡的服务,还要提供喂食的服务,你帮主人照看宠物进食。宠物进食自然就是宠物的行为(方法),你是照看宠物进食,又不是你进食,所以宠物来到宠物店后,你就要让宠物自己进食(即调用宠物的进食方法)。 用程序语言描述就是:
// 宠物类 class Animal{ // 进食方法 public void eat() { System.out.println("本宠物吃东西啦~~~~~~"); } } // 你学聪明了,参数一开始设置的就是宠物类,这样所有宠物都可以进来 public static void helpEat(Animal a) { // 然后再调用宠物本身的进食方法 a.eat(); // 打印的结果自然就是 “本宠物吃东西啦~~~~~~” } 复制代码
这么一看好像特别完美啊,但是你立马就发现问题了。每个不同的宠物品种喜欢吃的东西都不一样,吃东西的方式也不一样,可是现在你调用的是单一的宠物进食方法,不管是啥宠物进来打印的都是 “本宠物吃东西啦~~~~~~”。这就尴尬了,哈士奇是那种吃法,金毛是这种吃法,在你这难道就都变成了同一种吃法了吗。 所以要解决这个问题,应该体现出每个宠物品种自身的特性! 自身的特性用程序语言描述是啥呢? 就是方法的重写嘛:
// 哈士奇类继承了宠物类 class 哈士奇 extends Aniaml { @Override public void eat() { // 重写了父类的方法 System.out.println("本哈士奇开始犯二地吃东西啦~"); } } // 金毛类继承了宠物类 class 金毛 extends Aniaml { @Override public void eat() { // 重写了父类的方法 System.out.println("本金毛开始随和地吃东西啦~"); } } // 猫类继承了宠物类 class 猫 extends Aniaml { @Override public void eat() { // 重写了父类的方法 System.out.println("本猫开始高冷地吃东西啦~"); } } 复制代码
各品种的宠物重写了方法后,你宠物店再进行服务的时候效果立马就不一样了:
helpEat(哈士奇对象); // 传进来的参数类型是哈士奇类对象,打印结果是:"本哈士奇开始犯二地吃东西啦~" helpEat(金毛对象); // 传进来的参数类型是金毛类对象,打印结果是:"本金毛开始随和地吃东西啦~" helpEat(猫对象); // 传进来的参数类型是猫类对象,打印结果是:"本猫开始高冷地吃东西啦~" 复制代码
这就更能体现多态了,当父类的引用指向子类的对象时,调用的方法是子类重写后的方法,既体现了多种类型的传递,又体现了不同类型的特性。
多态是面向对象的核心机制,它将可扩展性达到了最好!
总结
面向对象的编程方式更贴近我们人类的理解和描述,很多人觉得难就是因为觉得这概念特别抽象,其实只要思路理清后,用平常生活中的思维去理解会发现使用面向对象时非常得心应手。
大家发现没有,这些特性其实在我们生活中随处可见,也非常好理解,这也就是我开头所说的:面向对象是为了方便我们构建代码,并不是增加我们构建代码的难度。
我个人认为,面向对象将程序语言描述和我们人类自然语言描述完美得结合在了一起。所以,面向对象只是比较抽象,但是并不难!希望大家理清思路后,带着愉快的心情去“享受”面向对象带来的便利!
最后针对于上面的技术知识点我总结出了相关知识点做成了文档和视频资料免费分享给大家
希望能帮助到您提高自己的技术升职加薪,也节省大家在网上搜索资料的时间来学习,也可以关注我一下以后会有更多干货分享。
领取方式:转发+关注,私信博主获取资料
-
JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)
2013-05-07 17:18:076.2.1 在类中给每个变量一个初始值 147 6.2.2 定义自己的引用 147 6.2.3 使用点操作符的技巧 148 6.2.4 类的数组 149 6.3 小结:Java其实是个类和对象的世界 152 6.4 习题 153 第7章 Java中的方法——给汽车... -
Java入门1·2·3:一个老鸟的Java学习心得.PART2(共3个)
2013-05-07 17:19:146.2.1 在类中给每个变量一个初始值 147 6.2.2 定义自己的引用 147 6.2.3 使用点操作符的技巧 148 6.2.4 类的数组 149 6.3 小结:Java其实是个类和对象的世界 152 6.4 习题 153 第7章 Java中的方法——给汽车... -
Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)
2013-05-07 17:20:126.2.1 在类中给每个变量一个初始值 147 6.2.2 定义自己的引用 147 6.2.3 使用点操作符的技巧 148 6.2.4 类的数组 149 6.3 小结:Java其实是个类和对象的世界 152 6.4 习题 153 第7章 Java中的方法——给汽车... -
java 面试题 总结
2009-09-16 08:45:34对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生类可以从它的基类那里继承方法和实例变量,并且类可以... -
面向对象的javascript系列文章(1)接口——是一个标准委员会
2017-03-25 20:30:38一般在java中对于接口的定义会是这样的:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为...在面向对象开发中,接口确实是一个特别抽象的名词,加上一些语法的赘述,“醉了~
”有木有。
一般在java中对于接口的定义会是这样的:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。(来源于百度百科
别打我,但是人家说的有错?)
这个定义完全就是在说怎么去创建使用一个接口,接口的特征啊。第一次学接口看到这个定义的时候 我有种这样的感觉,可能定义接口的作者会有这个心态:“你有种去理解,能get到算我输。”(开个玩笑了~毕竟人家是学术性的)读者可以看看我换个角度是怎么理解的,明白与否以及描述的理解上的错误 欢迎留言批评。
其实接口就是一个标准委员会,有ECMAScript标准委员会、http标准委员会、水龙头水管接口标准委员会…… 他们的职责无非就是制定某个行业某种商品的标准,以及去监督这个商品的产生是否遵循标准去执行,否则就去警告。
还不理解?没关系能理解标准委员会就好。在下面的第一节中会详细描述的。感受一下我扯淡的水平
一、到底什么是接口?
先定义两个东西水管和水龙头
当这个社会还是很单纯的就只有一家水官厂一家书龙头厂他们在商量好接头的型号为圆形之后,分别制作了一个模具,开始大规模的生产,生产的样子如下,他们貌似很开心的赚钱着。
当有一天,随着社会的需求不断增加,水龙头厂企业发现个这个矛头,然后就开始大力的研发模具生产新的型号的水龙头,这种水龙头是“互联网+”的产品,但是这家公司的设计师由于疏忽吧接头改为了三角形。生产如下:
这家水官厂发现接口变了,所以为了不错过商机,也跟着研发了新的接头的水管,但是仅仅是接头变了。
就这样随着社会的不断发展,需求逐渐扩大,水龙头厂就这么的不断研发着新的型号的模具、制造新的型号的产品……但只是研发模具的人员总是疏忽不断改变接头的型号,发展到是这样的:
你说,到最后谁能疯,当然是水官厂的研发磨具的人员了。他们站出来呐喊了,
水管厂研发磨具的人员:“水龙头的研发人员挺好了能不能别总是在改接头了说好的圆形呢
”,
水龙头厂也很冤枉啊,说:“我们这里研发人员经常换人他们并不知道之前是圆形的啊”。
水管厂研发磨具的人员:“你们知道吗?这些水管几乎都一样的就是接头变了,让我们还要加班重新开发新的模具
”。
最终水管厂研发磨具的人员和水龙头研发磨具的人员成立了一个水龙头水管接口标准委员会,这个委员会经过几天的讨论就郑重发布消息了:“标准如下:研发的任何新产品的模具接头只能是圆形的不能有其他型号。好处如下:(一)可以让任何一方不再制造无用的重复高相似的仅仅是接头不一样的模具,增加复用性(二)规定圆形之后可能有更好的稳定不同类型的水管不不同类型水龙头的搭配方式。(三)便于我们委员会的监督,如果谁不遵守标准谁就拉出去斩了……”。
之后的很多年,他们都不管去开发新的接口,所以水管厂和水龙头厂最终最在了一起。
用伪代码描述是这样的:
interface socket(){ final int yuan = "圆形"; int Type(); } class 智能水龙头 implement socket{ int Type(){ return yuan; } }; class 净水水龙头 implement socket{ int Type(){ return yuan; } }; class 水管 implement socket{ int Type(){ return yuan; } }; class 组装水龙头水管 { socket _水管; socket _水龙头; //先暂且不考虑水管和水龙头谁染都实现一个接头但不是一类东西的问题 void set水管(socket){ _水管 = socket; }; void set水龙头(socket){ _水龙头 = socket; }; void 组装(){ if(_水管.Type == _水龙头.Type){ 开始组装…… } } } var 组装1 = new 组装水龙头水管(); 组装1.set水管(new 智能水龙头()); 组装1.set水管(new 水管()); 组装1.组装(); var 组装2 = new 组装水龙头水管(); 组装2.set水管(new 净水水龙头()); 组装2.set水管(new 水管()); 组装2.组装();
二、接口的出现有哪些好处?
嗯 如果不喜欢这种很二逼的解析方式的话,可以看看下面这一个比较官方的解析,同时会说出什么是接口以及他的好处。
------------------------------------------------------------------------------------------------
标准委员会 =======> 接口 interface 不同种类的水龙头和水管的模具 =======> 实现接口的类 具体的水龙头和水管 =======> 类的对象
(1)提高代码的重用
在《设计模式》一书中提出的可复用的面向对象设计的第一条原则中就说到“针对接口而不是实现编程”,正如上述
所看到的没有标准委员会,将会出现什么情况? 各种各样重复的高相似的水管,或者各种各样相似的水龙头。这无疑增加了类的数量,并且有些类的相似程度还不少仅仅就是为了能够迎合水龙头的改变。如果针对接口去编程,那么无疑能够增加类的重用。
(2)解耦
考虑最复杂的情况,如果没有接口的话,每一种水龙头,对于水管内部这么一个类为了重用势必要添加ifelse语句进行对水龙头类型的检查,同时并调用他们的方法,这使得这一个水管类与其他水龙头类都有联系。如果有接口的话就好多了,水管与接口关联、任意种类的水龙头与接口关联,接口起到一个中间层,这样依赖性大大减少。
(3)稳定的通信方式
只要接口确定,并按标准实现,那么还担心类之间不能通信?
(4)便于测试和调试
只要发现有一个类没有实现接口的方法,或者传入的类型不是我想要的,那么标准委员会必然要行驶监督的权利。
(5)使得代码更稳固
更加稳固不如说可扩展性,比如我增加水管的类型,很简单其他的类不需要动,仅仅是只要能遵循接口就好,如果接口想扩展新方法,那么实现的类就必须去实现它。
综上所述:接口就是一种契约,一种标准,他是方法或者常量的集合,这些方法的名字参数必须确定,实现它的类严格按照这种这个名字这些参数去实现,否则抛出异常。
三、Java语言是怎么实现接口的?
这个实例时定义了一个磁盘接口,U盘、硬盘灯存储媒介都比如实现这种接口,也就是说,无论是哪种存储媒介都要保存到磁盘中去。
然后定义一个下载类,这里面可以根据不同媒介向磁盘写信息。
定义一个接口 磁盘 interface Disk(){ void save(File file); }; u盘和硬盘都是磁盘,都实现这个接口 class UDisk implement Disk{ void save(File file){} } class HardDisk implement Disk{ void save(File file){} } 一个需要用磁盘来存储的下载工具 class Download{ Disk disk; 用接口声明,我们不知道,也不用知道,我们未来会存到什么样的磁盘, 我们不依赖于任何类型的磁盘,我们只依赖于这个接口 void download(File file){ disk.save(file); } void setDisk(Disk disk){ this.disk=disk; } public static void main(String[] args){ Download download = new Download(); 设置存储目标为U盘 download.setDisk(new UDisk()); 文件被存到了U盘 download.download(file); 设置存储目标为硬盘 download.setDisk(new HardDisk()); 文件被存到了硬盘 download.download(file); 某天我们想把下载的文件保存到CD里边,我们只需要定义CDDisk类, 实现Disk接口就可以不对download本身做任何修改, 就可以方便的将文件下载到CD或其他介质里。 我们的Download类不依赖于任何具体的类,这样就解除了与任何具体存储设备的耦合! } }
这个例子展现出对下来类的重用,同时下载类和其他的存储媒介仅仅是通过save进行关联,并且这种关联还是下载类关联到Disk接口,其他存储媒介关联到Disk接口实现的,所以解耦。并且一筹添加新的媒介形式仅仅定义新的媒介就好只要实现接口不需要更改下载类。
四、Javascript语言是怎么实现接口的?
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script> /* 定义接口 返回的对象格式为 {name,method} 有一个静态方法 */ var Interface = (function (){ var Interface = function(name,methods){ if(typeof name !== 'string') throw typeError('Interface的name参数必须为string类型'); if(!Array.isArray(methods)) throw typeError('Interface的methods参数必须为Array类型'); this.name = name; this.methods = methods; } Interface._implement = function(obj,inter){ if(typeof obj !== 'object') throw typeError('Interface._implement的第一个参数必须为object类型'); if(!Array.isArray(inter)) throw typeError('Interface._implement的第二个参数必须为Array类型'); for(var i = 0; i<inter.length; i++){ var interItem = inter[i]; if(interItem.constructor !== Interface) throw typeError(interItem+'不是一个Interface类型'); for(var j = 0; j<interItem.methods.length; j++){ var m = interItem.methods[j]; if(!(m in obj)&&(typeof obj[m] !== 'function')){ throw new Error('在对象 '+obj+' 中,没有实现接口 '+interItem.name+' 的 '+m+' 方法!'); } } } return true; }; return Interface; })(); // 定义接口Disk var Disk = new Interface("Disk",["save"]); //定义U盘 硬盘类 // UDisk implements Disk function UDisk(){ }; UDisk.prototype.save = function(){ console.log("u盘正在保存"); }; // HardDisk implements Disk function HardDisk(){ } HardDisk.prototype.save = function(){ consloe.log("硬盘正在保存"); }; function CDDisk(){ } CDDisk.prototype.save = function(){ consloe.log("CD正在保存"); }; // 一个下载类 其中使用到各种媒介保存到磁盘中 function Download(){ this.Disk ; } Download.prototype.download = function(){ this.Disk.save(); }; Download.prototype.setDisk = function(disk){ Interface._implements(disk,[Disk]); this.Disk = disk; } var d = new Download(); Download.setDisk(new UDisk()); Download.download(); </script> </body> </html>
-
在一小时内学会 C#(txt版本)
2009-08-19 18:09:37现在思考当你要从其他命名空间的类中访问 HelloWorld 类。 复制内容到剪贴板 代码: using System; namespace AnotherNameSpace { class AnotherClass { public void Func() { Console.WriteLine ("Hello World... -
Spring事务的问题,bulkUpdate,或query.executeUpdate
2008-12-23 16:07:41谢谢你的解答,但是我还是不明白你的意思,你是指我的Dao中用了内部类吗,你所指的 “调用updateByIds方法 的代码 跳出你的当前类 然后在别的类调用当前了类的接口中的方法updateByIds ”是指什么意思,能不能说明白... -
在介绍 Java 怎么学之前我给大家介绍一下学完了能干什么,因为有目标的学习才是最高效的。 Java 这门语言,在公司里根据分工不同衍生出了众多的岗位或者技术方向。 我在 boss 直聘上搜索了 BAT 等大厂的岗位,目前有...
-
c#学习笔记.txt
2008-12-15 14:01:21virtual在派生类中声明其实现可由重写成员更改的方法或访问器。 volatile指示字段可由操作系统、硬件或并发执行的线程等在程序中进行修改。 9,语句 语句是程序指令。除非特别说明,语句都按顺序执行。C# 具有下列... -
C#微软培训教材(高清PDF)
2009-07-30 08:51:1711.1 方法的声明.124 11.2 方法中的参数.125 11.3 静态和非静态的方法.129 11.4 方法的重载.130 11.5 操作符重载.134 11.6 小 结.137 第十二章 域 和 属 性 .139 12.1 域 .139 12.2 属 性 .143 ... -
C#微软培训资料
2014-01-22 14:10:1711.1 方法的声明.124 11.2 方法中的参数.125 11.3 静态和非静态的方法.129 11.4 方法的重载.130 11.5 操作符重载.134 11.6 小 结.137 第十二章 域 和 属 性 .139 12.1 域 .139 12.2 属 性 .143 ... -
从编译的角度看为什么 Velocity 丑到哭
2020-12-30 18:08:48别想着在最初解析的同时完成双引号字符串的解析,例如 <code>#set($a = "today is: $util.format(\"20140318\")")</code> 这样的输入串,对双引号的转义会导致无法正确解析。 设计... -
软件工程教程
2012-07-06 23:10:29用例只描述参与者和系统在交互过程中做些什么,并不描述怎么做。 用例图 关联关系 用例图 泛化关系 用例图 泛化关系 用例图 用例图 用例图 用例用于什么情况? 不知道什么情况不用用例 如果没有用到用例,... -
XML轻松学习手册--XML肯定是未来的发展趋势,不论是网页设计师还是网络程序员,都应该及时学习和了解
2008-12-05 08:39:07面向对象的思想方法已经非常流行了,在编程语言(例如java,js)中,都运用面向对象的编程思想。在XML中,就是要将网页也作为一个对象来操作和控制,我们可以建立自己的对象和模板。与对象进行交流,如何命令对象,... -
枸杞的由来和技术栈
2021-01-02 15:11:32由于这些技术或者技术的使用方法都是我在日常工作中暂时用不到或者不能用的(必须考虑到团队的接受程度和开发效率),因此我写枸杞除了贺寿之外,实际上就是为了得到些经验踩一些坑,... -
Visual C++ 2008入门经典--详细书签版
2013-02-02 16:07:158.9.1 在数值类中重载运算符 425 8.9.2 重载递增和递减运算符 430 8.9.3 在引用类中重载运算符 431 8.9.4 实现引用类型的赋值运算符 433 8.10 小结 434 8.11 练习 435 第9章 类继承和虚函数 436 9.1 面向对象... -
Visual C++ 2008入门经典--源代码及课后练习答案
2013-02-02 16:13:25CruiseYoung提供的带有详细书签的电子... 8.9.1 在数值类中重载运算符 425 8.9.2 重载递增和递减运算符 430 8.9.3 在引用类中重载运算符 431 8.9.4 实现引用类型的赋值运算符 433 8.10 小结 434 8.11 练习 435 第... -
Oracle 9i & 10g编程艺术:深入数据库体系结构(09年度畅销榜TOP50)(08年度畅销榜TOP50)--详细书签版
2013-02-06 18:24:20在Oracle公司,Kyte专门负责Oracle数据库,他的任务是帮助使用Oracle数据库的客户,并与他们共同设计和构建系统,或者对系统进行重构和调优。在进入Oracle公司之前,Kyte是一名系统集成人员,主要为美国军方和政府... -
Oracle Database 9i10g11g编程艺术:深入数据库体系结构(第2版)--详细书签版
2013-02-03 11:42:53在本书第1版出版时隔4年后,Thomas Kyte及时了解了大家的这一迫切需求,根据他的实战经验以及人们最关心的问题对这本书做了全面补充和调整,以涵盖11g最受关注的多项特性。例如11g引入dbms_parallel_execute包来帮助... -
Oracle DBA突击:帮你赢得一份DBA职位--详细书签版
2013-02-06 15:56:40在这里仅列举两个最主要的原因,一方面,随着近年来企业信息化进程的深入,企业里各种系统的数据量持续上升,这一切给数据的管理、维护和安全带来了机会和挑战,另一方面,企业间同质化竞争的加剧,也迫使企业加强... -
Oracle Database 11g数据库管理艺术--详细书签版
2012-09-30 01:09:45书中内容主要集中在大多数企业常见的问题之上,如安装和升级到oracle database 11g数据库软件、创建数据库、导出和导入数据、数据库的备份与恢复、性能调优,等等。 本书还提供了dba完成本职工作必备的基本的uniix... -
Ajax.Dll各个版本无刷新组件
2014-12-15 11:17:021.先把Ajax.dll添加引用到项目中,别告诉我不会,如果连这个也不会就太那个了,和添加其他DLL一样,在项目上右击,菜单上有个[添加引用],然后一步一步把那个.DLL文件添加进来,之后你会在项目的引用中看到那个Ajax.... -
struts+javascript 分页问题请高手们解决一下
2009-10-19 10:38:02这个是login.action的类 请求执行里面的findAllUsers()方法 package org.login.actions; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet....