第九章 接口(下)

IEEE 802.1AS-2011 第九章 应用接口(API) 本文翻译自IEEE Standard for Local and metropolitan area networks—Timing and Synchronization for Time-Sensitive Applications in Bridged Local Area Networks 9. 应用接口 9.1 接口总览 以下子条款定义了ClockSource实体和ClockMaster... 阅读详情
             第九章    接口 (下)
9.4  Java中的多重继承
       接口不仅仅只是一种更纯粹形式的抽象类,它的目标比这要高。因为接口是根本没有任何具体实现的——也就是说,没有任何与接口相关的存储;因此,也就无法阻止多个接口的组合。这一点是很有价值的,因为你有时需要去表示"一个X是一个a和一个b以及一个c"。在C++中,组合多个类的接口的行为被称作多重继承。它可能会使你背负很沉重的包袱,因为每个类都有一个具体实现。在Java中,你可以执行相同的行为,但是只有一个类可以有具体实现;因此,通过组合多个接口,C++中的问题是不会在Java中发生的:
                                
                                              
     在导出类中,不强制要求必须有一个是抽象的或“具体的”(没有任何抽象方法的)基类。如果要从一个非接口的类继承,那么只能从一个类去继承。其余的基本元素都必须是接口。需要将所有的接口名都置于implements关键字之后,用逗号将它们一一隔开。可以继承任意多个接口,并可以向上转型为每个接口,因为每一个接口都是一个独立类型。下面的例子展示一个具体类组合数个接口之后产生了一个新类:
     interface CanFight{
     void fight();
}
interface CanSwim{
     void swim();
}
interface CanFly{
     void fly();
}
class ActionCharacter{
     public void fight(){}
}
class Hero extends ActionCharacter implements CanFight,CanSwim,CanFly{
     @Override
     public void fly() {}
     @Override
     public void swim() {}
}
public class Adventure {
     public static void t(CanFight x){
          x.fight();
     }
     public static void u(CanSwim x){
          x.swim();
     }
     public static void v(CanFly x){
          x.fly();
     }
     public static void w(ActionCharacter x){
          x.fight();
     }
     public static void main(String[] args) {
          Hero h = new Hero();
          t(h);
          u(h);
          v(h);
          w(h);
     }
}
       可以看到,Hero组合了具体类ActionCharacter和接口CanFight、CanSwim和CanFly。当通过这种方式将一个具体类和多个接口组合到一起时,这个具体类必须放在前面,后面跟着的才是接口(否则编译器会报错)。
      注意,CanFight接口与ActionCharacter类中的fight()方法的特征签名是一样的,而且,在Hero中并没有提供fight()的定义。可以扩展接口,但是得到的只是另一个接口。当想要创建对象时,所有的定义首先必须都存在。即使Hero没有显示地提供fight()的定义,其定义也因ActionCharacter而随之而来,这样就使得创建Hero对象成为了可能。
       在Adventure类中,可以看到有四个方法把上述各种接口和具体类作为参数。当Hero对象被创建时,它可以被传递给这些方法中的任何一个,这意味着它依次被向上转型为每一个接口。由于Java中这种设计接口的方式,使得这项工作不需要程序员付出任何特别的努力。
        一定要记住,前面的例子所展示的就是使用接口的核心原因:为了能够向上转型为多个基类型(以及由此而带来的灵活性)。然而,使用接口的第二个原因却是与使用抽象基类相同:防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。这就带来一个问题:我们应该使用接口还是抽象类?如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。事实上,如果知道某事物应该称为一个基类,那么第一选择应该使它称为一个接口(该主题在本章的总结中再次讨论)

9.5  通过继承来扩展接口
      通过继承,可以很容易地在接口中添加新的方法声明,还可以通过继承在新接口中组合数个接口。这两种情况都可以获得新的接口,就像在下例所看到的:
     interface Monster{
     void menace();
}
interface DangerousMonster extends Monster{
     void destroy();
}
interface Lethal{
     void kill();
}
class DragonZilla implements DangerousMonster{
     public void menace(){}
     public void destroy(){}
}
interface Vampire extends DangerousMonster,Lethal{
     void drinkBlood();
}
class VeryBadVampire implements Vampire{
     public void menace(){}
     public void destroy(){}
     public void kill(){}
     public void drinkBlood(){}
}
public class HorrorShow {
     static void u(Monster b){
          b.menace();
     }
     static void v(DangerousMonster d){
          d.menace();
          d.destroy();
     }
     static void w(Lethal l){
          l.kill();
     }
     public static void main(String[] args) {
          DangerousMonster barney = new DragonZilla();
          u(barney);
          v(barney);
          Vampire vlad = new VeryBadVampire();
          u(vlad);
          v(vlad);
          w(vlad);
     }
}

       DangerousMonster是Monster的直接扩展,它产生了一个新接口。DragonZilla中实现了这个接口。
       在Vampire中使用的语法仅适用于接口继承。一般情况下,只可以将extends用于单一类,但是可以引用多个基类接口。就像所看到的,只需用逗号将接口名一一分隔开即可。

9.5.1   组合接口时的名字冲突
       在实现多重继承时,可能会碰到一个小陷阱。在前面的例子中,CanFight和ActionCharacter都有一个相同的void fight()方法。这不是问题所在,因为该方法在二者中是相同的。相同的方法不会有什么问题,但是如果它们的签名或返回类型不同,又会怎么样呢?这有一个例子:
     interface I1{
     void f();
}
interface I2{
     int f(int i);
}
interface I3{
     int f();
}
class C{
     public int f(){
          return 1;
     }
}
class C2 implements I1,I2{
     public void f(){}
     public int f(int i){
          return 1;
     }
}
class C3 extends C implements I2{
     public int f(int i){
          return 1;
     }
}
class C4 extends C implements I3{
     public int f(){
          return 1;
     }
}
//class C5 extends C implements I1{}
//interface I4 extends I1,I3{}
   
       此时困难来了,因为覆盖、实现和重载令人不快地搅在了一起,而且重载方法仅通过返回类型是区分不开的。当撤销最后两行的注释时,下列错误消息就说明了这一切:
     The return types are incompatible for the inherited methods I1.f(), C.f()
     The return types are incompatible for the inherited methods I1.f(), I3.f()
    
     在打算组合的不同接口中使用相同的方法名通常会造成代码可读性的混乱,请尽量避免这种情况。

9.6  适配接口
       接口最吸引人的原因之一就是允许同一个接口具有多个不同的具体实现。在简单的情况中,它的体现形式通常是一个接受接口类型的方法,而该接口的实现和向该方法传递的对象则取决于方法的使用者。
       因此,接口的一种常见的用法就是前面提到的策略设计模式,此时你编写一个执行某些操作的方法,而该方法将接受一个同样是你指定的接口。你主要就是要声明:“你可以用任何你想要的对象来调用我的方法,只要你的对象遵循我的接口。”这使得你的方法更加灵活、通用,并更具可复用性。
       例如,Java SE5的Scanner类(在第13章中就更多地了解它)的构造器接受的就是一个Readable接口。你会发现Readable没有用作Java标准类库中其他任何方法的参数,它是单独为Scanner创建的,以使得Scanner不必将其参数限制为某个特定类。通过这种方式,Scanner可以作用于更多的类型。如果你创建了一个新的类,并且想让Scanner可以作用于它,那么你就应该让它成为Readable,就像下面这样:
     public class RandomWords implements Readable{
     private static Random rand=new Random(47);
     private static final char[] capitals="ABCDEFJ".toCharArray();
     private static final char[] lowers="abcdefj".toCharArray();
     private static final char[] vowels="aeiou".toCharArray();
     private int count;
     public RandomWords(int count){
          this.count=count;
     }
     @Override
     public int read(CharBuffer cb) throws IOException {
          if(count--==0){
               return -1;
          }
          cb.append(capitals[rand.nextInt(capitals.length)]);
          for(int i=0;i<4;i++){
               cb.append(vowels[rand.nextInt(vowels.length)]);
               cb.append(lowers[rand.nextInt(lowers.length)]);
          }
          cb.append(" ");
          return 10;
     }
@SuppressWarnings("resource")
public static void main(String[] args) {
     Scanner s = new Scanner(new RandomWords(10));
     while(s.hasNext()){
          System.out.println(s.next());
     }
}
}
运行结果:
Jajefuaaf
Aofebudof
Aoaaaiaoa
Fajudaeia
Jucaeeaif
Aaeediauf
Aufibibud
Duaaeeaid
Jududoaod
Dafiaeeod

        Readable接口只要求实现read()方法,在read()内部,将输入内容添加到CharBuffer参数中(有多种方法可以实现此目的,请查看CharBuffer的文档),或者在没有任何输出时返回-1.
        假设你有一个还未实现Readable的类,怎样才能让Scanner作用于它呢?下面这个类就是一个例子,它可以产生随机浮点数:
     public class RandomDoubles {
     private static Random rand=new Random(47);
     public double next(){
          return rand.nextDouble();
     }
     public static void main(String [] args){
          RandomDoubles rd = new RandomDoubles();
          for(int i=0;i<7;i++){
               System.out.println(rd.next());
          }
     }
}
运行结果:
0.7271157860730044 
0.5309454508634242 
0.16020656493302599 
0.18847866977771732 
0.5166020801268457 
0.2678662084200585 
0.2613610344283964

       我们再次使用了适配器模式,但是在本例中,被适配的类可以通过继承和实现Readable接口来创建。因此,通过使用interface关键字提供的伪多重继承机制,我们可以生成既是RandomDoubles又是Readable的新类:
     public class AdaptedRandomDouble extends RandomDoubles implements Readable{
     private int count;
     public AdaptedRandomDouble(int count){
          this.count=count;
     }
     @Override
     public int read(CharBuffer cb) throws IOException {
          if(count--==0){
               return -1;
          }
          String result=Double.toString(next())+"  ";
          cb.append(result);
          return result.length();
     }
     @SuppressWarnings("resource")
     public static void main(String[] args) {
          Scanner s = new Scanner(new AdaptedRandomDouble(7));
          while(s.hasNextDouble()){
               System.out.println(s.nextDouble());
          }
     }
}
运行结果:
0.7271157860730044
0.5309454508634242
0.16020656493302599
0.18847866977771732
0.5166020801268457
0.2678662084200585
0.2613610344283964

       因为在这种方式中,我们可以在任何现有类之上添加新的接口,所以这意味这让方法接受接口类型,是一种让任何类都可以对该方法进行适配的方式。这就是使用接口而不是类的强大之处。

9.7  接口中的域
       因为你放入接口中的任何域都是自动是static和final的,所以接口就成为了一种很便捷的用来创建常量组的工具。在Java SE5之前,这是产生与C或C++中的enum(枚举类型)具有相同效果的类型的唯一途径。因此在Java SE5之前的代码中你会看到下面这样的代码:
     public interface Months {
     int
         JANUARY=1,FEBRUARY=2,MARCH=3;
}
      请注意,Java中标识具有常量初始化值的static final时,会使用大写字母的风格(在一个标识符中用下划线来分隔多个单词)。接口中的域自动是public的,所以没有显式地指明这一点。
       有了Java SE5,你就可以使用更加强大而灵活的enum关键字,因此,使用接口来群组常量已经显得没什么意义了。但是,当你阅读遗留的代码时,在许多情况下你可能还是会碰到这种旧的习惯用法。在第19章中可以看到更多的关于使用enum的细节说明。

9.7.1  初始化接口中的域
        在接口中定义的域不能是“空final”,但是可以被非常量表达式初始化。例如:
     public interface RandVals {
     Random RAND=new Random(47);
     int RANDOM_INT=RAND.nextInt(10);
     long RANDOM_LONG=RAND.nextLong()*10;
     float RANDOM_FLOAT=RAND.nextLong()*10;
     double RANDOM_DOUBLE=RAND.nextDouble()*10;
}

public class TestRandvals {
     public static void main(String[] args) {
          System.out.println(RandVals.RANDOM_INT);
          System.out.println(RandVals.RANDOM_LONG);
          System.out.println(RandVals.RANDOM_FLOAT);
          System.out.println(RandVals.RANDOM_DOUBLE);
     }

}
运行结果:
8
-32032247016559954
-8.5939291E18
5.779976127815049


9.8  嵌套接口
       接口可以嵌套在类或其他接口中。这揭示了许多非常有趣的特性:
       class A{
     interface B{
          void f();
     }
     public class BImp implements B{
          public void f(){}
     }
     private class BImp2 implements B{
          public void f(){}
     }
     public interface C{
          void f();
     }
     class CImp implements C{
          public void f(){}
     }
     private class CImp2 implements C{
          public void f(){}
     }
     private interface D{
          void f();
     }
     private class DImp implements D{
          public void f(){}
     }
     public class DImp2 implements D{
          public void f(){}
     }
     public D getd(){
          return new DImp2();
     }
     private D dRef;
     public void receiveD(D d){
          dRef=d;
          dRef.f();
     }
}
interface E{
     interface G{
          void f();
     }
     public interface H{
          void f();
     }
     void g();
//     private interface I{}
}
public class NestingInterfaces {
     public class BImp implements A.B{
          public void f(){}
     }
     class CImp implements A.C{
          public void f(){}
     }
//     class CImp implements A.D{
//          public void f(){}
//     }
     class EImp implements E{
          public void g(){}
     }
     class EGImp implements E.G{
          public void f(){}
     }
     class EImp2 implements E{
          public void g(){}
          class EG implements E.G{
               public void f(){}
          }
     }
public static void main(String[] args) {
     A a = new A();
//     A.D getd = a.getd();
//     A.DImp2 di2=a.getd();
//     a.getd().f();
     A a2 = new A();
     a2.receiveD(a.getd());
}
}

      在类中嵌套接口的语法是相当显而易见的,就像非嵌套接口一样,可以拥有public和“包访问”两种可视性。
      作为一种新添加的方式,接口也可以被实现为private的,就像在A.D中所看到的(相同的语法既适用于嵌套接口,也适用于嵌套类)。那么private的嵌套接口能带来什么好处呢?读者可能会猜想,它只能够被实现为DImp中的一个private内部类,但是A.DImp2展示了同样可以被实现为public类,但是,A.DImp2只能被其自身所使用。你无法说它实现了一个private接口D。因此,实现一个private接口只是一种方式,它可以强制该接口中的方法定义不要添加任何类型信息(也就是说,不允许向上转型)。
      getD()方法使我们陷入了一个进退两难的境地,这个问题与private接口相关:它是一个返回对private接口的引用的public方法。你对这个方法的返回值能做些什么呢?在main()中,可以看到数次尝试使用返回值的行为都失败了。只有一种方式可成功,那就是将返回值交给有权使用它的对象。在本例中,是另一个A通过receiveD()方法来实现的。
       接口E说明接口彼此之间可以嵌套。然而,作用于接口的各种规则,特别是所有的接口元素都必须是public的,在此都会被严格执行。因此。嵌套在另外一个接口中的接口自动就是public的,而不能声明为private的。
       NestingInterfaces 展示了嵌套接口的各种实现方式。特别要注意的是,当实现某个接口时,并不需要实现嵌套在其内部的任何接口。而且,private接口不能在定义它的类之外被实现。
      添加这些特性的最初原因可能是出于对严格语法一致性的考虑,但是我总认为,一旦你了解了某种特性,就总能够找到它的用武之地。

9.9  接口与工厂
       接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象。理论上,通过这种方式,我们的代码将完全与接口的实现分离,这就使得我们可以透明地将某个实现替换为另一个实现。下面的实例展示了工厂方法的结构:
     interface Service{
     void method1();
     void method2();
}
interface ServiceFactory{
     Service getService();
}
class Implementation1 implements Service{
     public Implementation1() {}
     public void method1(){
          System.out.println("Implementation1 method1");
     }
     public void method2(){
          System.out.println("Implementation1 method2");
     }
}
class Implementation1Factory implements ServiceFactory{
     public Service getService(){
          return new Implementation1();
     }
}
class Implementation2 implements Service{
     public Implementation2() {}
     public void method1(){
          System.out.println("Implementation2 method1");
     }
     public void method2(){
          System.out.println("Implementation2 method2");
     }
}
class Implementation2Factory implements ServiceFactory{
     public Service getService(){
          return new Implementation2();
     }
}
public class Factories {
     public static void serviceConsumer(ServiceFactory fact){
          Service s = fact.getService();
          s.method1();
          s.method2();
     }
     public static void main(String[] args) {
          serviceConsumer(new Implementation1Factory());
          serviceConsumer(new Implementation2Factory());
     }

}

    如果不是用工厂方法,你的代码就必须在某处指定将要创建的Service的确切类型,以便调用合适的构造器。
     为什么我们想要添加这种额外级别的间接性呢?一个常见的原因是想要创建框架:假设你正在创建一个对弈游戏系统,例如,在相同的棋盘上下国际象棋和西洋跳棋:
     interface Game{
     boolean move();
}
interface GameFactory{
     Game getGame();
}
class Checkers implements Game{
     private int moves=0;
     private static final int MOVES=3;
     public boolean move(){
          System.out.println("Checkers move"+moves);
          return ++moves!=MOVES;
     }
}
class CheckersFactory implements GameFactory{
     public Game getGame(){
          return new Checkers();
     }
}
class Chess implements Game{
     private int moves=0;
     private static final int MOVES=4;
     public boolean move(){
          System.out.println("Chess move"+moves);
          return ++moves!=MOVES;
     }
}
class ChessFactory implements GameFactory{
     public Game getGame(){
          return new Chess();
     }
}
public class Games {
     public static void playGame(GameFactory factory){
          Game game = factory.getGame();
          while(game.move());
     }
public static void main(String[] args) {
     playGame(new CheckersFactory());
     playGame(new ChessFactory());
}
}
运行结果:
Checkers move0
Checkers move1
Checkers move2
Chess move0
Chess move1
Chess move2
Chess move3

       如果Games类表示一段复杂的代码,那么这种方式就允许你在不同类型的游戏中复用这段代码。你可以再想象一些能够从这个模式中受益的更加精巧的游戏。
       在下一章中,你将可以看到另一种更优雅的工厂实现方式,那就是使用匿名内部类。

9.10  总结
        “确定接口是理想选择,因而应该总是选择接口而不是具体的类。”这其实是一种引诱。当然,对于创建类,几乎在任何时刻,都可以替代为创建一个接口和一个工厂。
          许多人都掉进了这种诱惑的陷阱,只要有可能就去创建接口和工厂。这种逻辑看起来好像是因为需要使用不同的具体实现,因此总是应该添加这种抽象性。这实际上已经变成了一种草率的设计优化。
         任何抽象性都应该是应真正的需求而产生的。当必需时,你应该重构接口而不是到处添加额外级别的间接性,并由此带来的额外复杂性。这种额外的复杂性非常显著,如果你让某人去处理这种复杂性,只是因为你意识到由于以防万一而添加了新接口,而没有其他更有说服力的原因,那么好吧,如果我碰上了这种事,那么就会质疑此人所作的所有设计了。
         恰当的原则应该是优先选择类而不是接口。从类开始,如果接口必需性变得非常明确,那么就进行重构。接口是一种重要的工具,但是它们容易被滥用。
第九章、接口开发 一、查询接口开发 2 2 2 2 二、增加接口开发 三、删除接口开发 四、更新接口开发 五、复合查询接口开发 2 2 2 2 阅读详情

相关推荐

FreeFEM++下载安装和使用

最近要利用机器学习求解一些偏微分方程,对于一些复杂的偏微分方程,需要一些精度比较高的参考解,导师推荐了FreeFEM++软件。首次使用,特此记录一下,以备以后查阅。 1、FreeFEM++简介 FreeFEM是开源的有限元模拟系统,有法国利翁斯实验室、埃尔和玛丽居里大学共同开发,在世界范围内广泛使用。 2、FreeFEM++去何处下载? 下载地址:https://freefem.org/ 点击Download,然后会跳转到 https://github.com/FreeFem/FreeFem-source

夜晓岚的博客 1万+

第9章接口(java编程思想)

9.1 抽象类和方法 包含抽象方法的类被称为抽象类,如果一个类包含一个或多个抽象方法,该类必须被限定为抽象的(否则,编译器就会报错)。 如果想要继承一个抽象类,那么必须为这个新类定义抽象类中所有的方法,如果不这么做,那么导出类也是抽象类,且编译器会强制我们使用abstract来限定这个类。(不能为抽象类创建任何对象) 9.2接口 一个接口表示"所有实现了该特定接口的类看起来都像这样"。因此接口被用来建立类与类之间的协议。 要让一个类遵循某个特定接口(或是一组接口),需要使用implements关键字,“in

printf_myself的博客 176

Vivado+VCS+Verdi三件套实战:如何高效仿真AXI VIP并快速查看波形

本文详细介绍了如何利用Vivado+VCS+Verdi工具链高效仿真AXI VIP并快速查看波形。通过环境配置、Vivado工程准备、VCS编译与仿真优化以及Verdi波形分析技巧,实现仿真速度的数量级提升,显著提高FPGA开发效率。

red88的博客 999

<java编程思想>(thing in java) 阅读笔记(第七章至第十章)

第七章 复用类  初始化这些引用,可以在代码中的下列位置进行:1、在定义对象的地方。这意味着它们总是能够在构造器被调用之前被初始化。2、在类的构造器中。3、就在正要使用这些对象之前。这种方式成为惰性初始化。在生成对象不值得及不必每次都生成对象的情况下。 7.2继承类  129页 在继承过程中,需要先声明“新类与旧类相似”。这种声明是通过类的主体的左边花括号之前,书写后面紧随基类名称的

SKY_L的博客 536

PVT(Process Voltage Temperature)

芯片PVT

网始如芯个人博客 3万+

【前端】【面试】【业务场景】前端如何获取并生成设备唯一标识

问题:前端如何获取并生成设备唯一标识?核心要点:浏览器原生信息有限,但通过组合多个维度可生成设备指纹(Device Fingerprint),用于唯一标识设备。常见方式浏览器信息(User-Agent)屏幕与系统参数本地存储标识(localStorage / cookie)第三方指纹库(如 FingerprintJS)方式优点缺点手动组合指纹实现简单不稳定,识别率低持久化强容易被用户清除识别率高、稳定性好依赖第三方库IP 地址识别网络识别粗略共享网络环境下重复可能大。

qq_59344127的博客 1793

抽象类、接口、多态特性

1. 抽象类本身不能被实例化,可以没有抽象方法 2. 父类与接口有相同的方法时,不会产生冲突,因为只会有一份方法的实现 package com.yjq.cn.interface public abstract class AbstractTest { int i = 10; public static int f(int i) { return ++i; }

dai_的专栏 1998

达梦数据库修改最大连接数

达梦数据库的最大连接数推荐配置与服务器内存有关。不应设置得过大,否则容易导致出现OOM。文件中整型的参数值。DSC环境下,除了特殊参数以外,其他参数值会在OK节点上同步。返回值:当前DM.INI文件中对应的参数值。功能说明:返回DM.INI文件中。:DM.INI文件中的参数名。

Sebastien23的博客 3331

Java 接口——4

package lianxi3; public interface CanSwim { void swim(); } package lianxi3; public interface Canfly { void fly(); } package lianxi3; public abstract cla...

weixin_30633949的博客 126

fast-lio运行步骤(使用velodyne数据)

使用fast-lio运行velodyne数据

ericdowney 4768

【2025最新版】间接平差——以水准网平差为例 (python详细过程版)

水准网间接平差的python代码实现。博客长期更新,本文最新更新时间为:2025年5月20日。

点云侠的博客 1702

关于接口的几点问题

1. 接口可以包含域,这些域隐式地是static和final的(即使你不写上),因此命名格式应为大写+下划线分隔。 2. 可以选择在接口中显式地将方法声明为public的,但是即使不这么做,它也是public的。因此在实现接口时,实现的方法必须被定义为public的。 3. 接口组合时的名字冲突问题: eg. interface I1{ void f()

重度拖延症患者 2655

知识库构建革命:基于Agent的智能检索系统设计

本文聚焦“基于Agent的智能检索系统”这一前沿技术,系统讲解其设计逻辑、核心技术与落地方法。我们将覆盖从基础概念(如Agent如何“理解”知识)到实战代码(如何用Python搭建原型系统)的全链路内容,帮助技术开发者、企业知识管理负责人理解这一技术为何能颠覆传统知识库。本文将按“问题引入→核心概念→技术原理→实战落地→未来趋势”的逻辑展开:先用“老图书馆的困境”故事引出传统知识库的问题;再用“智能图书管理员”类比解释Agent如何革新检索;接着拆解NLP、对话管理、知识推理等核心技术;

AI智能探索者的博客 724

thinking in java 笔记 思维导图 第九章 接口

mythling的专栏 620

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

第九章 接口

文章目录1.抽象类和抽象方法2.接口3.完全解耦复用代码4.Java的多重继承5.通过继承来拓展接口6.适配接口7.接口中的域8.嵌套接口9.接口与工厂 1.抽象类和抽象方法 抽象类(抽象基类):通用接口建立起一种基本形式,以此表示导出类的共同部分 如果一个类包含一个或多个抽象方法,该类必须限定为抽象类 如果从一个抽象继承的,并像创建该新类对象,那么就必须为基类中的所有抽象方法提供方法定义 我们可以创建一个没有任何抽象方法的抽象类 抽象类和抽象方法可以使类的抽象性明确起来,并告诉用户和编译器怎么使用他们

小名同学 22万+

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Java编程思想第四版读书笔记——第九章 接口

这章介绍了适配器设计模式和策略设计模式。 第九章  接口 接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法。 1、抽象类和抽象方法 public abstract void f(); 创建抽象类是希望通过这个通用接口操纵一系列类。如果一个类包含大于等于一个抽象方法,那么这个类就是抽象类,必须用abstract关键字来限定这个抽象类。 如果试图直接创

severusyue的博客 1738

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【JAVA SE】第九章 接口

【JAVA SE】第九章 接口

2022年毕业的萌新程序猿,输出一下自己的学习内容~ 428

第九章:接口

第九章:接口 接口和内部类为我们提供了一种接口和实现分离的更加结构化的方法。 一、抽象类和抽象方法(abstract) 抽象类:将所有导出类的共同部分抽取出来,作为一个公共的接口(方法) 优点:可以利用这个接口(抽象类)操作一系列类 特点:1、含有抽象方法的类,可以含有不抽象的具体实现方法,必定是抽象类(abstract),使用抽象限制。 ​ 2、当然抽象类,可以没有抽象方法。也无法创建对象(...

jue6628的博客 342

第九章 抽象类和接口

Java面向对象基础 第九章 抽象类和接口 一、抽象类 1、抽象方法 (1)对于父类的有些方法,子类在继承父类之后,都会对这些方法进行重写,来满足自己的业务需求,那么向这样的方法,就没有必要存在方法体,那么Java就提供了抽象方法这一概念。 (2)使用abstract关键字修饰的没有方法题的方法,就称之为抽象方法。抽象方法存在的最大作用就是约定子类应该具有该方法,并且必须对这些抽象方法进行重写,提供可运行的方法体。 (3)抽象方法的语法结构: [访问修饰符] abstract 返回值类型 方法名(

yrxfight的博客 219

第九章 抽象类 & 接口

9.1 abstract 概述 类中有相似方法,但是又有不同,此方法应定义为抽象方法,类也必须为抽象类。 特点: 1)方法只有声明没有实现 2)抽象类不可以被实例化 3)抽象类的子类必须覆盖其所有抽象方法才能被实例化 9.2 抽象类细节 1)有构造函数,用于其子类实例化 2)抽象类可以不包含抽象方法,目的是不让该类被实例化 (eg:AWT Adapter) 3)不能与ab

Alex Bai的博客 290
上一篇: 第九章 接口(上)
下一篇: 第十章 内部类(上)
OODeveloper
博客等级 码龄12年 43粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值