⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sect14.htm

📁 this is the most basic to learn python
💻 HTM
📖 第 1 页 / 共 5 页
字号:
you want to create. In addition, if the prototyping fails, the
<B>factory(&#160;)</B> method will assume that it&#146;s because a particular
<B>Class</B> object wasn&#146;t in the list, and it will attempt to load it. By
loading the prototypes dynamically like this, the <B>Trash</B> class
doesn&#146;t need to know what types it is working with, so it doesn&#146;t
need any modifications when you add new types. This allows it to be easily
reused throughout the rest of the chapter.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_362">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c12:trash:Trash.py
# Base <font color=#0000ff>class</font> <font color=#0000ff>for</font> Trash recycling examples.

<font color=#0000ff>class</font> Trash:
  private double weight
  <font color=#0000ff>def</font> __init__(self, double wt): weight = wt 
  <font color=#0000ff>def</font> __init__(self):
  <font color=#0000ff>def</font> getValue(self)
  <font color=#0000ff>def</font> getWeight(self): <font color=#0000ff>return</font> weight 
  # Sums the value of Trash given an
  # Iterator to any container of Trash:
  <font color=#0000ff>def</font> sumValue(self, Iterator it):
    double val = 0.0f
    <font color=#0000ff>while</font>(it.hasNext()):
      # One kind of RTTI:
      # A dynamically-checked cast
      Trash t = (Trash)it.next()
      val += t.getWeight() * t.getValue()
      <font color=#0000ff>print</font> (
        <font color=#004488>"weight of "</font> +
        # Using RTTI to get type
        # information about the <font color=#0000ff>class</font>:
        t.getClass().getName() +
        <font color=#004488>" = "</font> + t.getWeight())

    <font color=#0000ff>print</font> <font color=#004488>"Total value = "</font> + val

  # Remainder of <font color=#0000ff>class</font> provides 
  # support <font color=#0000ff>for</font> prototyping:
  private static List trashTypes = 
    ArrayList()
  <font color=#0000ff>def</font> factory(self, Messenger info):
    <font color=#0000ff>for</font>(int i = 0 i &lt; len(trashTypes) i++):
      # Somehow determine the type
      # to create, <font color=#0000ff>and</font> create one:
      Class tc = (Class)trashTypes.get(i)
      <font color=#0000ff>if</font> (tc.getName().index(info.id) != -1):
        <font color=#0000ff>try</font>:
          # Get the dynamic constructor method
          # that takes a double argument:
          Constructor ctor = tc.getConstructor(
              Class[]{ double.<font color=#0000ff>class</font> )
          # Call the constructor  
          # to create a object:
          <font color=#0000ff>return</font> (Trash)ctor.newInstance(
            Object[]{Double(info.data))
         catch(Exception ex):
          ex.printStackTrace(System.err)
          throw RuntimeException(
            <font color=#004488>"Cannot Create Trash"</font>)
        
      

    # Class was <font color=#0000ff>not</font> <font color=#0000ff>in</font> the list. Try to load it,
    # but it must be <font color=#0000ff>in</font> your <font color=#0000ff>class</font> path!
    <font color=#0000ff>try</font>:
      <font color=#0000ff>print</font> <font color=#004488>"Loading "</font> + info.id
      trashTypes.add(Class.forName(info.id))
     catch(Exception e):
      e.printStackTrace(System.err)
      throw RuntimeException(
        <font color=#004488>"Prototype not found"</font>)

    # Loaded successfully. 
    # Recursive call should work:
    <font color=#0000ff>return</font> factory(info)

  public static <font color=#0000ff>class</font> Messenger:
    public String id
    public double data
    public Messenger(String name, double val):
      id = name
      data = val

# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The basic <B>Trash</B> class
and <B>sumValue(&#160;)</B> remain as before. The rest of the class supports the
prototyping pattern. You first see two
<A NAME="Index54"></A><A NAME="Index55"></A>inner classes (which are made
<B>static</B>, so they are inner classes only for code organization purposes)
describing exceptions that can occur. This is followed by an <B>ArrayList
</B>called <B>trashTypes</B>, which is used to hold the <B>Class</B> references.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_363">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In <B>Trash.factory(&#160;)</B>, the
<B>String</B> inside the <B>Messenger </B>object <B>id </B>(a different version
of the <B>Messenger</B> class than that of the prior discussion) contains the
type name of the <B>Trash </B>to be created; this <B>String</B> is compared to
the <B>Class</B> names in the list. If there&#146;s a match, then that&#146;s
the object to create. Of course, there are many ways to determine what object
you want to make. This one is used so that information read in from a file can
be turned into objects.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_364">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Once you&#146;ve discovered which kind
of <B>Trash</B> to create, then the <A NAME="Index56"></A>reflection methods
come into play. The <A NAME="Index57"></A><B>getConstructor(&#160;)</B> method
takes an argument that&#146;s an array of <A NAME="Index58"></A><B>Class</B>
references. This array represents the arguments, in their proper order, for the
constructor that you&#146;re looking for. Here, the
<A NAME="Index59"></A><A NAME="Index60"></A>array is dynamically created using
the Java 1.1<A NAME="Index61"></A> array-creation syntax:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_365">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Class[]:double.<font color=#0000ff>class</font></PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">This code
assumes that every <B>Trash</B> type has a constructor that takes a <B>double
</B>(and notice that <B>double.class</B> is distinct from <B>Double.class</B>).
It&#146;s also possible, for a more flexible solution, to call
<A NAME="Index62"></A><B>getConstructors(&#160;)</B>, which returns an array of
the possible constructors.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_366">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">What comes back from
<B>getConstructor(&#160;) </B>is a reference to a
<A NAME="Index63"></A><B>Constructor</B> object (part of
<B>java.lang.reflect</B>). You call the constructor dynamically with the method
<A NAME="Index64"></A><B>newInstance(&#160;)</B>, which takes an array of
<B>Object</B> containing the actual arguments. This array is again created using
the Java 1.1<A NAME="Index65"></A> syntax:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_367">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Object[]{Double(Messenger.data)</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In
this case, however, the <B>double</B> must be placed inside a wrapper class so
that it can be part of this array of objects. The process of calling
<B>newInstance(&#160;)</B> extracts the <B>double</B>, but you can see it is a
bit confusing&#151;an argument might be a <B>double </B>or a <B>Double</B>, but
when you make the call you must always pass in a <B>Double</B>. Fortunately,
this issue exists only for the primitive types.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_368">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Once you understand how to do it, the
process of creating a new object given only a <B>Class</B> reference is
remarkably simple. Reflection also allows you to call methods in this same
dynamic fashion.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_369">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Of course, the appropriate <B>Class</B>
reference might not be in the <B>trashTypes</B> list. In this case, the
<B>return</B> in the inner loop is never executed and you&#146;ll drop out at
the end. Here, the program tries to rectify the situation by loading the
<B>Class</B> object dynamically and adding it to the <B>trashTypes</B> list. If
it still can&#146;t be found something is really wrong, but if the load is
successful then the <B>factory</B> method is called
<A NAME="Index66"></A><A NAME="Index67"></A>recursively to try again.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_370">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">As you&#146;ll see, the beauty of this
design is that this code doesn&#146;t need to be changed, regardless of the
different situations it will be used in (assuming that all <B>Trash</B>
subclasses contain a constructor that takes a single <B>double</B> argument).
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_371">Add Comment</A></FONT><A NAME="_Toc534420136"></A><BR></P></DIV>
<A NAME="Heading87"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Trash subclasses</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To fit into the prototyping scheme, the
only thing that&#146;s required of each new subclass of <B>Trash</B> is that it
contain a constructor that takes a <B>double</B> argument. Java reflection
handles everything else.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_372">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here are the different types of
<B>Trash</B>, each in their own file but part of the <B>Trash</B> package
(again, to facilitate reuse within the chapter):
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_373">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c12:trash:Aluminum.py 
# The Aluminum <font color=#0000ff>class</font> with prototyping.

<font color=#0000ff>class</font> Aluminum(Trash):
  private static double val = 1.67f
  <font color=#0000ff>def</font> __init__(self, double wt): .__init__(wt) 
  <font color=#0000ff>def</font> getValue(self): <font color=#0000ff>return</font> val 
  <font color=#0000ff>def</font> setValue(self, double newVal):
    val = newVal

# :~</PRE></FONT></BLOCKQUOTE>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c12:trash:Paper.py 
# The Paper <font color=#0000ff>class</font> with prototyping.

<font color=#0000ff>class</font> Paper(Trash):
  private static double val = 0.10f
  <font color=#0000ff>def</font> __init__(self, double wt): .__init__(wt) 
  <font color=#0000ff>def</font> getValue(self): <font color=#0000ff>return</font> val 
  <font color=#0000ff>def</font> setValue(self, double newVal):
    val = newVal

# :~</PRE></FONT></BLOCKQUOTE>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c12:trash:Glass.py 
# The Glass <font color=#0000ff>class</font> with prototyping.

<font color=#0000ff>class</font> Glass(Trash):
  private static double val = 0.23f
  <font color=#0000ff>def</font> __init__(self, double wt): .__init__(wt) 
  <font color=#0000ff>def</font> getValue(self): <font color=#0000ff>return</font> val 
  <font color=#0000ff>def</font> setValue(self, double newVal):
    val = newVal

# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">And here&#146;s a new type of
<B>Trash</B>:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_374">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c12:trash:Cardboard.py 
# The Cardboard <font color=#0000ff>class</font> with prototyping.

<font color=#0000ff>class</font> Cardboard(Trash):
  private static double val = 0.23f
  <font color=#0000ff>def</font> __init__(self, double wt): .__init__(wt) 
  <font color=#0000ff>def</font> getValue(self): <font color=#0000ff>return</font> val 
  <font color=#0000ff>def</font> setValue(self, double newVal):
    val = newVal

# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see that, other than
the constructor, there&#146;s nothing special about any of these classes.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_375">Add Comment</A></FONT><A NAME="_Toc534420137"></A><BR></P></DIV>
<A NAME="Heading88"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Parsing Trash from an external file</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The information about <B>Trash</B>
objects will be read from an outside file. The file has all of the necessary
information about each piece of trash on a single line in the form
<B>Trash:weight</B>, such as:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_376">Add Comment</A></FONT><BR></P></DIV>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -